Skip to main content

FACEHARD — native Python port, verbatim clone + CLI

A faithful Python reimplementation of FACEHARD 8.0, Nathan Okun's face-hardened naval armour penetration program (QuickBASIC, 2018). It reproduces both the program's numbers and its exact text output, validated against the generated BASIC working oracle (fh_oracle) by differential fuzzing. Intentional oracle corrections are documented separately.

Two ways to use it: a modern CLI (facehard run/pen/list) and a byte-faithful clone of the original interactive program (facehard emulate). Stdlib-only, pipx-installable.

Versions. The package is versioned independently of the model: this is package 1.0.0, reproducing Okun's FACEHARD 8.0 (8 August 2018). facehard.MODEL_VERSION and facehard --version both report the model version alongside the package version.

Source. Okun's original programs, papers and armour data are published at NavWeaps — The Nathan Okun Collection.

Install

pipx install facehard
facehard --version

CLI

facehard                     interactive wizard (modern menus)
facehard emulate             the ORIGINAL FACEHARD interactive session, verbatim
facehard run   [options]     one impact; --output narrative|limits|plug|metrics|json|all
facehard pen   [options]     penetration thickness at a striking velocity
facehard list  armors|nations|projectiles [--nation N]

run/pen scenario flags: --armor 1-25 --nation 1-8 --proj N -d/--diameter -w/--weight -b/--body-weight -v/--velocity -o/--obliquity; backing --wood --cement --metal --metal-type --metal-plates; nose loss --remove {none,cap,windscreen,caphead} --windscreen-wt --caphead-wt. run also takes -t/--thickness (the plate to shoot); pen omits it because it computes the thickness defeated.

Library API

from facehard import calc, results, render_results, penetration, names

calc(armor=14, nation=1, proj=18, TA=16, D=16, WT=2700, WB=2048, OB=30).vltru
results(armor=14, nation=1, proj=18, TA=12, D=16, WT=2700, WB=2048, OB=30, VS=2200)
render_results(armor=14, nation=1, proj=18, TA=12, D=16, WT=2700, WB=2048,
               OB=30, VS=2200, show_limits=True)          # verbatim BASIC text
penetration(armor=14, nation=1, proj=18, D=16, WT=2700, WB=2048, V=2500, OB=0)  # 29.5 in

Every numeric menu choice also has a named IntEnum — drop-in for the plain numbers, which stay valid everywhere:

from facehard import penetration, Armor, Nation, USProjectile, projectiles

Nation.UK == 2                                            # original menu numbers, unchanged
penetration(armor=Armor.BRITISH_CA, nation=Nation.USA,
            proj=USProjectile.APC_6IN_MK35_16IN_MK8,      # 16-in Mk 8 (IOWA)
            D=16, WT=2700, WB=2048, V=2500, OB=0)

projectiles(Nation.JAPAN).APC_TYPE91                      # per-nation projectile menus
Armor.JAPANESE_VH.menu_text                               # the original menu line

Nation, Armor, BackingMetal (the metal_type parameter), and one projectile enum per nation (USProjectile, BritishProjectile, GermanProjectile, FrenchProjectile, ItalianProjectile, JapaneseProjectile, AustroHungarianProjectile, RussianProjectile). The short names summarise menu lines that often cover several marks — member.menu_text is authoritative.

All of calc/results/render_results accept backing, nose-covering loss (remove, windscreen_wt, caphead_wt), and manual armour overrides (armor_overrides={"Q": 0.8, "UB": 60, ...} for UB/Q/QDAM/CARTWL/CMPND/THNCHL/SOFTSHAT/THKTHN).

Coverage — the whole program

Layer Status
Ballistic limits (N1–N4, H1–H4) ported, 100% vs BASIC
Post-impact results (outcome, exit angle, plug weights, remaining velocity, effective BL) ported, 100%
Verbatim results narrative (RESULTSPRINT + damage flags) ported, word-for-word
Backing (wood/cement/metal) & nose-covering loss (decapping) ported, 100%
Manual armour-parameter overrides ("modify parameters" screen) ported, applies + verbatim
Interactive shell (menus, info pages, prompts, re-run state) ported, verbatim (facehard emulate)

Not reproduced: nothing functional — only the DOS graphics-mode screen clears (cosmetic) differ.

Fidelity — how close to the BASIC?

precision_audit.py (1500 fuzzed examples, deterministic):

  • Zero velocity deviations across 6,818 ballistic-limit and post-impact velocity comparisons.
  • Exit angles agree exactly in the retained 10,000-case differential campaign.
  • The remaining differences are BASIC display rounding of plug weights to one decimal place (maximum 0.05 lb).

The generated working oracle uses double precision and contains the documented post-impact-limit correction in ORACLE_PATCHES.md.

Verbatim-text fuzzers confirm the same at the string level: fuzz_narrative.py 99.97% of result lines, fuzz_emulate.py 99.98% of full-session lines, fuzz_override.py 100% of override sessions — residual diffs are those same sub-unit display roundings.

Layout

Path Role
facehard/ installable package: model.py, emulate.py, cli.py, names.py
fh_oracle compiled BASIC oracle; rebuild via build_qb64.py + QB64-PE
facehard.bas / build_qb64.py the merged BASIC and its generator
ORACLE_PATCHES.md intentional model corrections applied to the generated oracle
facehard_run.py drives fh_oracle, parses its output
facehard_native.py back-compat shim → facehard.model
validate_native.py / validate_results.py limit & post-impact sweeps vs BASIC
precision_audit.py exact deviation audit (identical / off-by-1 / ≥2)
fuzz_native/narrative/emulate/override.py differential fuzzers
reproduce_table4_native.py reproduces the published comparison table, pure Python

Licence

Not open-source. The penetration mechanics and associated IP — including the formulas, decision logic, data tables, and original FACEHARD program flow and text — belong to the estate of Nathan Okun and, per NavWeaps' terms, may not be used commercially without prior written permission. The Python implementation and its original additions are Copyright © 2026 Adrian Beale and are released under the PolyForm Noncommercial License 1.0.0. The combined distribution is for noncommercial use only; commercial use may require permission from both rights holders. See LICENSE and NOTICE.

Release files for facehard 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for facehard 1.0.0
File Size Uploaded
facehard-1.0.0.tar.gz 101.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for facehard 1.0.0
File Interpreter ABI Platform
facehard-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 202.7 kB

Release files / facehard-1.0.0.tar.gz

Download URL facehard-1.0.0.tar.gz
Size 101.2 kB
Tags Source
SHA-256 checksum
How to use checksums
e8a14e22e7da0175d60548a7d048efbe4f31754545e3ba7eb6600468f9382c7e
BLAKE2b-256 checksum
How to use checksums
4f05e7a26843b71244ce1715aa5b6b91c2291c2b21b321778edca72eee19a7d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.0

Release files / facehard-1.0.0-py3-none-any.whl

Download URL facehard-1.0.0-py3-none-any.whl
Size 101.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4a76c062a27dd2f3f1a58af58021cb38f040203c51ca1377bbb583fccdd040ed
BLAKE2b-256 checksum
How to use checksums
152fcf23bbc658bf26810f9bb6e0ff7e79f138b4f87f603b68f58e63a770ff9b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.0

Release history Release notifications | RSS feed

1.1.2

2 release files

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page