Files
oniagent/tools/oni_analyzer.py
root 0e17e8a6ac feat: complete ONI Agent project with full Mod API, Python toolchain, and development guide
- Implement all Mod API endpoints (buildings, research, geysers, alerts, critters, deconstruct, prioritize, research, schedule, wardrobe)
- Enhance Python tools with comprehensive CLI, analysis (O2/food/power/temp/water), and 7 blueprints (SPOM, toilet, ranch, farm, cooling, bedroom)
- Add utility scripts: auto_repair, auto_analyze, watch mode, setup
- Write Agent-Mod integration constraints and development guide
- Create skills directory with ONI agent skill definition
2026-05-22 08:44:56 +08:00

222 lines
7.6 KiB
Python

import json
import sys
from oni_api import api_get, api_post
def get_game_state():
return {
'game': api_get('/api/state/game'),
'resources': api_get('/api/state/resources'),
'duplicants': api_get('/api/state/duplicants'),
'buildings': api_get('/api/state/buildings'),
'research': api_get('/api/state/research'),
'geysers': api_get('/api/state/geysers'),
'alerts': api_get('/api/state/alert'),
'critters': api_get('/api/state/critters'),
}
def as_dict(resources):
if not isinstance(resources, list):
return {}
return {r.get('name'): r for r in resources}
def analyze_o2(resources):
r = as_dict(resources)
o2 = r.get('Oxygen', {}).get('amount', 0)
algae = r.get('Algae', {}).get('amount', 0)
pw = r.get('PollutedWater', {}).get('amount', 0)
warnings = []
if o2 < 100:
warnings.append(("CRITICAL", f"Oxygen critically low ({o2:.0f} kg)"))
elif o2 < 500:
warnings.append(("WARN", f"Oxygen declining ({o2:.0f} kg)"))
if algae < 1000:
warnings.append(("WARN", f"Algae running out ({algae:.0f} kg) — build electrolyzer"))
elif algae < 5000:
warnings.append(("INFO", f"Algae moderate ({algae:.0f} kg) — plan SPOM"))
if pw > 50000:
warnings.append(("INFO", f"Polluted water abundant ({pw:.0f} kg) — use for reed fiber / pincha pepper"))
return warnings
def analyze_food(resources):
r = as_dict(resources)
cal = r.get('Calories', {}).get('amount', 0)
warnings = []
if cal < 100000:
warnings.append(("CRITICAL", f"Food shortage ({cal:.0f} kcal)"))
elif cal < 500000:
warnings.append(("WARN", f"Food declining ({cal:.0f} kcal)"))
elif cal > 2000000:
warnings.append(("INFO", f"Food surplus ({cal:.0f} kcal) — consider more dupes"))
return warnings
def analyze_power(resources):
r = as_dict(resources)
coal = r.get('Coal', {}).get('amount', 0)
hydrogen = r.get('Hydrogen', {}).get('amount', 0)
natgas = r.get('NaturalGas', {}).get('amount', 0)
warnings = []
if coal < 5000:
warnings.append(("WARN", f"Coal low ({coal:.0f} kg) — diversify power"))
if hydrogen > 20000:
warnings.append(("INFO", f"Hydrogen stockpiled ({hydrogen:.0f} kg) — add generators"))
if natgas > 10000:
warnings.append(("INFO", f"Natural gas abundant ({natgas:.0f} kg) — tap for power"))
return warnings
def analyze_temp(resources):
r = as_dict(resources)
warnings = []
for key in ['Temperature', 'AvgTemp']:
t = r.get(key, {}).get('amount')
if t:
if t > 50:
warnings.append(("CRITICAL", f"Overheating ({t:.0f}°C)"))
elif t > 35:
warnings.append(("WARN", f"High temperature ({t:.0f}°C)"))
elif t < -5:
warnings.append(("WARN", f"Too cold ({t:.0f}°C)"))
return warnings
def analyze_water(resources):
r = as_dict(resources)
water = r.get('Water', {}).get('amount', 0)
pw = r.get('PollutedWater', {}).get('amount', 0)
warnings = []
if water < 10000:
warnings.append(("WARN", f"Clean water low ({water:.0f} kg) — conserve / filter PW"))
if pw > water * 2 and water > 0:
warnings.append(("INFO", f"More polluted water than clean — build water purifier"))
return warnings
def suggest_actions(warnings, alerts):
suggestions = []
for sev, msg in warnings:
if 'Oxygen' in msg or 'oxygen' in msg:
if 'CRITICAL' in sev:
suggestions.append("URGENT: Build algae deoxidizer or electrolyzer immediately")
else:
suggestions.append("Build or expand SPOM (Self-Powered Oxygen Module)")
elif 'Food' in msg or 'food' in msg:
if 'CRITICAL' in sev:
suggestions.append("URGENT: Harvest wild plants or cook mush fry")
else:
suggestions.append("Expand mealwood farm or start hatch ranching")
elif 'Coal' in msg:
suggestions.append("Diversify power: hydrogen generator, natural gas, or solar")
elif 'Hydrogen' in msg:
suggestions.append("Build more hydrogen generators and battery bank")
elif 'NaturalGas' in msg:
suggestions.append("Build natural gas generator + gas pipe system")
elif 'temperature' in msg.lower() or 'overheat' in msg.lower():
suggestions.append("Check cooling loop; add liquid pipe thermo sensor")
elif 'water' in msg.lower() and 'low' in msg.lower():
suggestions.append("Dig more water sources or filter polluted water")
if isinstance(alerts, list):
for a in alerts:
msg = a.get('message', '') or a.get('title', '')
ml = msg.lower()
if 'oxygen' in ml or 'breathable' in ml:
suggestions.append("Build or expand electrolyzer setup (SPOM)")
elif 'food' in ml or 'starving' in ml:
suggestions.append("Expand mealwood farm or start ranching")
elif 'heat' in ml or 'temperature' in ml:
suggestions.append("Check cooling system, expand steam turbine setup")
elif 'power' in ml or 'wattage' in ml:
suggestions.append("Add power generation (hydrogen/natural gas)")
return list(dict.fromkeys(suggestions))
def print_report(state):
g = state.get('game', {})
if 'error' in g:
print(f"[!] Cannot connect to game: {g['error']}")
return False
resources = state.get('resources', [])
alerts = state.get('alerts', [])
all_warnings = []
all_warnings += analyze_o2(resources)
all_warnings += analyze_food(resources)
all_warnings += analyze_power(resources)
all_warnings += analyze_temp(resources)
all_warnings += analyze_water(resources)
critical = [w for w in all_warnings if w[0] == 'CRITICAL']
warns = [w for w in all_warnings if w[0] == 'WARN']
infos = [w for w in all_warnings if w[0] == 'INFO']
suggestions = suggest_actions(all_warnings, alerts)
print("=" * 52)
print(" ONI Analysis Report")
print("=" * 52)
print(f" Cycle: {g.get('cycle', '?')}")
print(f" Duplicants: {g.get('duplicantCount', '?')}")
print(f" World: {g.get('worldName', '?')}")
print(f" Buildings: {len(state.get('buildings', []) or [])}")
print(f" Critters: {len(state.get('critters', []) or [])}")
print(f" Geysers: {len(state.get('geysers', []) or [])}")
print(f" Research done: {sum(1 for t in (state.get('research') or []) if t.get('isComplete'))}")
print()
if critical:
print(f" [CRITICAL] {len(critical)} issues")
for _, msg in critical:
print(f" ! {msg}")
print()
if warns:
print(f" [WARN] {len(warns)} issues")
for _, msg in warns:
print(f" * {msg}")
print()
if infos:
print(f" [INFO] {len(infos)} notes")
for _, msg in infos:
print(f" i {msg}")
print()
if not all_warnings:
print(" Status: All stable")
print()
if suggestions:
print(f" Suggestions ({len(suggestions)}):")
for s in suggestions:
print(f" -> {s}")
print()
print(f" Alerts in-game: {len(alerts) if isinstance(alerts, list) else 0}")
if isinstance(alerts, list):
for a in alerts:
print(f" [{a.get('severity', '?')}] {a.get('title', '?')}: {a.get('message', '')}")
print("=" * 52)
return True
if __name__ == '__main__':
state = get_game_state()
if not print_report(state):
sys.exit(1)