No test suite existed before this, which is exactly how a real regression (the bold-span coordinate-squashing bug, and the 'Type#id:'/'<ref>: <value>' header collision, both from this session) went unnoticed until manually re-triggered. One test per format, cross-referenced against the full commit history so nothing already shipped gets silently dropped by a future change: tests/test_ocr.py: standard blocks, the calibration target line, destruction reports (digit and letter id), train-arrival intel, ad-hoc Enemy installations (+ their destroyed reports), Listening Post/Coastal Battery, Marine Garrison fire-support requests, multi- word RP names, bare-name-header targets, the bold-span coordinate- squashing regression specifically, forward-observer report triangulation, the '<ref>: <value>' clue grammar (+ its header- collision regression specifically), 16-point compass tolerance, and grid-only coordinates. tests/test_solver.py: direct bearing+distance resolution, two-bearing triangulation, genuine two-distance ambiguity, the nested-circles compromise-point fallback, toleranced bearings never being used to triangulate, and manual coord overrides clearing a stale note. Runs via ============================= test session starts ============================== platform linux -- Python 3.14.6, pytest-8.4.2, pluggy-1.6.0 rootdir: /home/dodox/Projects/FeNigma configfile: pytest.ini plugins: anyio-4.13.0 collected 21 items tests/test_ocr.py ............... [ 71%] tests/test_solver.py ...... [100%] ============================== 21 passed in 0.72s ============================== (pythonpath configured in pytest.ini), dev-only dependency in requirements-dev.txt so the app itself stays dependency-light. Documented in the README.
51 lines
3.3 KiB
Markdown
51 lines
3.3 KiB
Markdown
<h1 align="center">
|
|
<img src='icon.png' width="250px">
|
|
<br>
|
|
<b>FeNigma</b>
|
|
<br>
|
|
</h1>
|
|
|
|
<p align="center"><b>Fe</b> (iron) + enigma, we solve the geometric puzzles.</p>
|
|
|
|
A companion app that mostly automates **IRON NEST: Heavy Turret Simulator** for you. Select the game's typewriter orders (selecting text in-game copies it to your clipboard automatically) and it solves the geo puzzle and the trajectory math, handing you ready-to-fire commands: elevation, azimuth, number of powder charges. Screenshotting works the same way when a selection isn't practical. Select or screenshot the field log the same way and it picks up kills and newly-spotted units automatically. You can also plan strikes and scout flights of your own. Pure screen-reading, no game files touched, no input injected.
|
|
|
|

|
|
|
|
## What it does
|
|
|
|
- **Reads orders, solves the geometry.** Copy (or screenshot) the in-game typewriter text and it parses absolute grid refs and relative bearing/distance descriptions, then resolves everything into map coordinates, chained clues ("Bearing 293 from Alpha") included. The map shows its work: the actual bearing lines/circles behind each resolved position. When a description is genuinely ambiguous (two intersections), both candidates are shown instead of guessing.
|
|
- **Calculates the shot.** Every resolved target gets a live firing card: elevation, azimuth, and minimum powder charge, computed from the Nest.
|
|
- **Tracks the battle.** A second copy/screenshot of the field log marks units destroyed and folds in newly-spotted contacts, merging with what's already known instead of duplicating it.
|
|
- **Plans strikes.** Drop a strike anywhere on the map and pick a shell to preview its blast radius before committing.
|
|
- **Plans scout flights.** Click the map to plot a scout flight's sweep path: it anchors to the large grid square you're pointing at and reads the heading off exactly where in that square you click, previewed live before you commit.
|
|
- **Watches the clipboard for you.** Toggle auto-watch and every new screenshot or copied intel text gets read and merged automatically, no manual fetch between orders.
|
|
|
|
## Install
|
|
|
|
```bash
|
|
./install.sh
|
|
```
|
|
|
|
Sets up a venv for the Python deps (Pillow, numpy, pytesseract) and checks for the system packages that pip can't install: GTK4/libadwaita bindings and tesseract. If either is missing it prints the package names for your distro and stops, install those and re-run.
|
|
|
|
## Run
|
|
|
|
```bash
|
|
./run.sh
|
|
```
|
|
|
|
Uses the venv from `install.sh` if one exists, otherwise falls back to system `python3`. GTK apps with this app ID are single-instance, if a run gets killed uncleanly it can leave a zombie registered on D-Bus and silently no-op the next launch. If `./run.sh` seems to do nothing, `pgrep -af fenigma` and kill any stragglers first.
|
|
|
|
## Tests
|
|
|
|
```bash
|
|
pip install -r requirements-dev.txt
|
|
pytest
|
|
```
|
|
|
|
Regression coverage for every intel-text format the OCR pipeline understands and the solver's geometry, in `tests/`. Run this before trusting a change to `ocr.py`/`solver.py`, several of the formats have collided with each other in non-obvious ways before.
|
|
|
|
## Stack
|
|
|
|
GTK4 + libadwaita (PyGObject) for the UI, Tesseract (via pytesseract) for OCR, Pillow/numpy for preprocessing. Details on the coordinate system, OCR formats, and solver internals live in code comments (`solver.py`, `ocr.py`, `models.py`) rather than here.
|