#!/usr/bin/env python3 """ ONI Agent — Game State Analyzer ================================ Fetches comprehensive game state and produces actionable analysis across 6 dimensions: oxygen, food, power, temperature, water, research. """ import json, sys, io # Fix GBK encoding if sys.stdout.encoding and sys.stdout.encoding.upper() in ('GBK', 'GB2312', 'CP936'): sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') from oni_api import api_get def get_data(endpoint): r = api_get(endpoint) if r.get("success"): return r.get("data", r) return None def main(): game = get_data('/api/state/game') resources = get_data('/api/state/resources') or [] buildings = get_data('/api/state/buildings') or [] dups = get_data('/api/state/duplicants') or [] alert_data = get_data('/api/state/alert') or [] research = get_data('/api/state/research') or {} rdict = {} if isinstance(resources, list): for r in resources: rdict[r.get('name', '')] = r.get('amountKg', 0) # Building type counts btypes = {} for b in buildings if isinstance(buildings, list) else []: bid = b.get('id', '') btypes[bid] = btypes.get(bid, 0) + 1 print("=" * 56) print(" ONI Agent — Game Analysis") print("=" * 56) if game: speed_str = f"{game.get('gameSpeed','?')}x speed" if not game.get('isPaused') else "PAUSED" print(f" Cycle {game.get('cycle','?')} | {game.get('duplicantCount','?')} dupes | " f"{game.get('gridWidth','?')}x{game.get('gridHeight','?')} grid | {speed_str}") print() # 1. Oxygen print("─── Oxygen ───") o2 = rdict.get('Oxygen', 0) algae = rdict.get('Algae', 0) pw = rdict.get('PollutedWater', 0) water = rdict.get('Water', 0) has_elec = 'Electrolyzer' in btypes has_diff = 'OxygenDiffuser' in btypes print(f" O2: {o2:.0f} kg Algae: {algae:.0f} kg Water: {water:.0f} kg") if o2 < 500: print(f" ⚠ CRITICAL: Oxygen low! {o2:.0f} kg remaining") if not has_elec and not has_diff: print(f" ⚠ No oxygen production. Build OxygenDiffuser or plan SPOM") elif not has_elec and algae < 1000: print(f" ⚠ Algae running out ({algae:.0f} kg). Build Electrolyzer (SPOM)") if water > 50000 and not has_elec: print(f" ℹ Water abundant ({water:.0f} kg). Good time for SPOM") if pw > 100000: print(f" ℹ Polluted Water: {pw:.0f} kg — sieve into water or use for thimble reed") # 2. Food print(f"\n─── Food ───") calories = rdict.get('Calories', 0) dirt = rdict.get('Dirt', 0) has_farm = any(bid in ('PlanterBox', 'FarmTile') for bid in btypes) has_grill = 'ElectricGrill' in btypes print(f" Calories: {calories:.0f} kcal Dirt: {dirt:.0f} kg") if calories < 200000: print(f" ⚠ CRITICAL: Food shortage! {calories:.0f} kcal") elif calories < 500000: print(f" ⚠ Food declining ({calories:.0f} kcal). Build farm") if not has_farm: print(f" ℹ No farm. Build 5x PlanterBox + plant Mealwood (uses Dirt)") if not has_grill and has_farm: print(f" ℹ No grill. Build ElectricGrill for better food quality") # 3. Power print(f"\n─── Power ───") coal = rdict.get('Carbon', 0) hydrogen = rdict.get('Hydrogen', 0) has_manual = 'ManualGenerator' in btypes has_coal = 'CoalGenerator' in btypes has_hydro = 'HydrogenGenerator' in btypes has_solar = 'SolarPanel' in btypes has_natgas = 'NaturalGasGenerator' in btypes print(f" Coal: {coal:.0f} kg Hydrogen: {hydrogen:.0f} kg") gen_list = [] if has_manual: gen_list.append('Manual') if has_coal: gen_list.append('Coal') if has_hydro: gen_list.append('Hydrogen') if has_natgas: gen_list.append('NaturalGas') if has_solar: gen_list.append('Solar') print(f" Generators: {', '.join(gen_list) if gen_list else 'None'}") if coal < 1000 and has_coal: print(f" ⚠ Coal low ({coal:.0f} kg). Diversify power production") if not has_hydro and 'Electrolyzer' in btypes: print(f" ℹ Have Electrolyzer but no HydrogenGenerator — wasting H2!") if not any([has_manual, has_coal, has_hydro, has_natgas, has_solar]): print(f" ⚠ No power generation! Build ManualGenerator or CoalGenerator") # 4. Temperature print(f"\n─── Temperature ───") ice = rdict.get('Ice', 0) + rdict.get('CrushedIce', 0) + rdict.get('Snow', 0) granite = rdict.get('Granite', 0) igneous = rdict.get('IgneousRock', 0) print(f" Ice/Snow: {ice:.0f} kg") if ice > 0: print(f" ℹ Ice available for cooling if melted") # 5. Water print(f"\n─── Water ───") salt_water = rdict.get('SaltWater', 0) brine = rdict.get('Brine', 0) print(f" Water: {water:.0f} kg Polluted Water: {pw:.0f} kg Salt Water: {salt_water:.0f} kg") if water < 10000 and pw < 10000: print(f" ⚠ Low water! Collect from geysers or filter polluted water") if water < 1000: print(f" ⚠ CRITICAL: Water nearly empty!") # 6. Research print(f"\n─── Research ───") completed = research.get('completedTechs', []) print(f" Completed: {len(completed)} techs") if completed: print(f" Last: {completed[-1] if completed else 'none'}") # 7. Alerts if alert_data: print(f"\n─── Active Alerts ───") for a in alert_data: print(f" [{a.get('severity','?')}] {a.get('title','?')}") print() print("=" * 56) print(" Analysis complete.") print("=" * 56) if __name__ == "__main__": main()