dcs_liberation/game/naming.py
Dan Albert 0be6952a93 Rename UnitType.name what it is: the variant ID.
This property affects safe compat because the ID is what gets preserved
in the save, but it's unfortunately also used as the display name, which
means changing the display name breaks save compat. It also prevents us
from changing display names without breaking faction definitions.

This is the first step in fixing that. The next is adding a separate
display_name property that can be updated without breaking either of
those.
2023-08-09 21:53:25 -07:00

563 lines
9.9 KiB
Python

from __future__ import annotations
import random
import time
from typing import Any, List, TYPE_CHECKING
from dcs.country import Country
from game.dcs.aircrafttype import AircraftType
from game.dcs.unittype import UnitType
if TYPE_CHECKING:
from game.ato.flight import Flight
ALPHA_MILITARY = [
"Alpha",
"Bravo",
"Charlie",
"Delta",
"Echo",
"Foxtrot",
"Golf",
"Hotel",
"India",
"Juliet",
"Kilo",
"Lima",
"Mike",
"November",
"Oscar",
"Papa",
"Quebec",
"Romeo",
"Sierra",
"Tango",
"Uniform",
"Victor",
"Whisky",
"XRay",
"Yankee",
"Zulu",
"Zero",
]
ANIMALS: tuple[str, ...] = (
"AARDVARK",
"AARDWOLF",
"ADDER",
"ALBACORE",
"ALBATROSS",
"ALLIGATOR",
"ALPACA",
"ANACONDA",
"ANOLE",
"ANTEATER",
"ANTELOPE",
"ANTLION",
"ARAPAIMA",
"ARCHERFISH",
"ARGALI",
"ARMADILLO",
"ASP",
"AUROCHS",
"AXOLOTL",
"BABIRUSA",
"BABOON",
"BADGER",
"BANDICOOT",
"BARRACUDA",
"BARRAMUNDI",
"BASILISK",
"BASS",
"BAT",
"BEAR",
"BEAVER",
"BEETLE",
"BELUGA",
"BETTONG",
"BINTURONG",
"BISON",
"BLOODHOUND",
"BOA",
"BOBCAT",
"BONGO",
"BONITO",
"BUFFALO",
"BULLDOG",
"BULLFROG",
"BULLSHARK",
"BUMBLEBEE",
"BUNNY",
"BUTTERFLY",
"CAIMAN",
"CAMEL",
"CANARY",
"CAPYBARA",
"CARACAL",
"CARP",
"CASTOR",
"CAT",
"CATERPILLAR",
"CATFISH",
"CENTIPEDE",
"CHAMELEON",
"CHEETAH",
"CHICKEN",
"CHIMAERA",
"CICADA",
"CICHLID",
"CIVET",
"COBIA",
"COBRA",
"COCKATOO",
"COD",
"COELACANTH",
"COLT",
"CONDOR",
"COPPERHEAD",
"CORAL",
"CORGI",
"COTTONMOUTH",
"COUGAR",
"COW",
"COYOTE",
"CRAB",
"CRANE",
"CRICKET",
"CROCODILE",
"CROW",
"CUTTLEFISH",
"DACHSHUND",
"DEER",
"DINGO",
"DIREWOLF",
"DODO",
"DOG",
"DOLPHIN",
"DONKEY",
"DOVE",
"DRACO",
"DRAGON",
"DRAGONFLY",
"DUCK",
"DUGONG",
"EAGLE",
"EARWIG",
"ECHIDNA",
"EEL",
"ELEPHANT",
"ELK",
"EMU",
"ERMINE",
"FALCON",
"FANGTOOTH",
"FAWN",
"FENNEC",
"FERRET",
"FINCH",
"FIREFLY",
"FISH",
"FLAMINGO",
"FLEA",
"FLOUNDER",
"FOX",
"FRINGEHEAD",
"FROG",
"FROGMOUTH",
"GAR",
"GAZELLE",
"GECKO",
"GENET",
"GERBIL",
"GHARIAL",
"GIBBON",
"GIRAFFE",
"GOOSE",
"GOPHER",
"GORILLA",
"GOSHAWK",
"GRASSHOPPER",
"GREYHOUND",
"GRIZZLY",
"GROUPER",
"GROUSE",
"GRYPHON",
"GUANACO",
"GULL",
"GUPPY",
"HADDOCK",
"HAGFISH",
"HALIBUT",
"HAMSTER",
"HARAMBE",
"HARE",
"HARRIER",
"HAWK",
"HEDGEHOG",
"HERMITCRAB",
"HERON",
"HERRING",
"HIPPO",
"HORNBILL",
"HORNET",
"HORSE",
"HUNTSMAN",
"HUSKY",
"HYENA",
"IBEX",
"IBIS",
"IGUANA",
"IMPALA",
"INSECT",
"IRUKANDJI",
"ISOPOD",
"JACKAL",
"JAGUAR",
"JELLYFISH",
"JERBOA",
"KAKAPO",
"KANGAROO",
"KATYDID",
"KEA",
"KINGFISHER",
"KITTEN",
"KIWI",
"KOALA",
"KOMODO",
"KRAIT",
"LADYBUG",
"LAMPREY",
"LEMUR",
"LEOPARD",
"LIGHTFOOT",
"LION",
"LIONFISH",
"LIZARD",
"LLAMA",
"LOACH",
"LOBSTER",
"LOCUST",
"LORIKEET",
"LUNGFISH",
"LYNX",
"MACAW",
"MAGPIE",
"MALLARD",
"MAMBA",
"MAMMOTH",
"MANATEE",
"MANDRILL",
"MANTA",
"MANTIS",
"MARE",
"MARLIN",
"MARMOT",
"MARTEN",
"MASTIFF",
"MASTODON",
"MAVERICK",
"MAYFLY",
"MEERKAT",
"MILLIPEDE",
"MINK",
"MOA",
"MOCKINGBIRD",
"MOLE",
"MOLERAT",
"MOLLY",
"MONGOOSE",
"MONKEY",
"MONKFISH",
"MONSTER",
"MOOSE",
"MORAY",
"MOSQUITO",
"MOTH",
"MOUSE",
"MUDSKIPPER",
"MULE",
"MUSK",
"MYNA",
"NARWHAL",
"NAUTILUS",
"NEWT",
"NIGHTINGALE",
"NUMBAT",
"OCELOT",
"OCTOPUS",
"OKAPI",
"OLM",
"OPAH",
"OPOSSUM",
"ORCA",
"ORYX",
"OSPREY",
"OSTRICH",
"OTTER",
"OWL",
"OX",
"OYSTER",
"PADDLEFISH",
"PADEMELON",
"PANDA",
"PANGOLIN",
"PANTHER",
"PARAKEET",
"PARROT",
"PEACOCK",
"PELICAN",
"PENGUIN",
"PERCH",
"PEREGRINE",
"PETRAL",
"PHEASANT",
"PIG",
"PIGEON",
"PIGLET",
"PIKE",
"PIRANHA",
"PLATYPUS",
"POODLE",
"PORCUPINE",
"PORPOISE",
"POSSUM",
"POTOROO",
"PRONGHORN",
"PUFFERFISH",
"PUFFIN",
"PUG",
"PUMA",
"PYTHON",
"QUAGGA",
"QUAIL",
"QUOKKA",
"QUOLL",
"RABBIT",
"RACOON",
"RAGDOLL",
"RAT",
"RATTLESNAKE",
"RAVEN",
"REINDEER",
"RHINO",
"ROACH",
"ROBIN",
"SABERTOOTH",
"SAILFISH",
"SALAMANDER",
"SALMON",
"SANDFLY",
"SARDINE",
"SAWFISH",
"SCARAB",
"SCORPION",
"SEAHORSE",
"SEAL",
"SEALION",
"SERVAL",
"SHARK",
"SHEEP",
"SHOEBILL",
"SHRIKE",
"SHRIMP",
"SIDEWINDER",
"SILKWORM",
"SKATE",
"SKINK",
"SKUNK",
"SLOTH",
"SLUG",
"SNAIL",
"SNAKE",
"SNAPPER",
"SNOOK",
"SPARROW",
"SPIDER",
"SPRINGBOK",
"SQUID",
"SQUIRREL",
"STAGHORN",
"STARFISH",
"STINGRAY",
"STINKBUG",
"STOUT",
"STURGEON",
"SUGARGLIDER",
"SUNBEAR",
"SWALLOW",
"SWAN",
"SWIFT",
"SWORDFISH",
"TAIPAN",
"TAKAHE",
"TAMARIN",
"TANG",
"TAPIR",
"TARANTULA",
"TARPON",
"TARSIER",
"TAURUS",
"TERMITE",
"TERRIER",
"TETRA",
"THRUSH",
"THYLACINE",
"TIGER",
"TOAD",
"TORTOISE",
"TOUCAN",
"TREADFIN",
"TREVALLY",
"TRIGGERFISH",
"TROUT",
"TUATARA",
"TUNA",
"TURKEY",
"TURTLE",
"URCHIN",
"VIPER",
"VULTURE",
"WALLABY",
"WALLAROO",
"WALLEYE",
"WALRUS",
"WARTHOG",
"WASP",
"WATERBUCK",
"WEASEL",
"WEEVIL",
"WEKA",
"WHALE",
"WILDCAT",
"WILDEBEEST",
"WOLF",
"WOLFHOUND",
"WOLVERINE",
"WOMBAT",
"WOODCHUCK",
"WOODPECKER",
"WORM",
"WRASSE",
"WYVERN",
"YAK",
"ZEBRA",
"ZEBU",
)
class NameGenerator:
number = 0
infantry_number = 0
aircraft_number = 0
convoy_number = 0
cargo_ship_number = 0
jtac_number = 0
animals: list[str] = list(ANIMALS)
existing_alphas: List[str] = []
@classmethod
def reset(cls) -> None:
cls.number = 0
cls.infantry_number = 0
cls.convoy_number = 0
cls.cargo_ship_number = 0
cls.jtac_number = 0
cls.animals = list(ANIMALS)
cls.existing_alphas = []
@classmethod
def reset_numbers(cls) -> None:
cls.number = 0
cls.infantry_number = 0
cls.aircraft_number = 0
cls.convoy_number = 0
cls.cargo_ship_number = 0
cls.jtac_number = 0
@classmethod
def next_aircraft_name(cls, country: Country, flight: Flight) -> str:
cls.aircraft_number += 1
if flight.custom_name:
name_str = flight.custom_name
else:
name_str = "{} {}".format(flight.package.target.name, flight.flight_type)
return "{}|{}|{}|{}|".format(
name_str, country.id, cls.aircraft_number, flight.unit_type.variant_id
)
@classmethod
def next_unit_name(cls, country: Country, unit_type: UnitType[Any]) -> str:
cls.number += 1
return "unit|{}|{}|{}|".format(country.id, cls.number, unit_type.variant_id)
@classmethod
def next_infantry_name(cls, country: Country, unit_type: UnitType[Any]) -> str:
cls.infantry_number += 1
return "infantry|{}|{}|{}|".format(
country.id,
cls.infantry_number,
unit_type.variant_id,
)
@classmethod
def next_awacs_name(cls, country: Country) -> str:
cls.number += 1
return "awacs|{}|{}|0|".format(country.id, cls.number)
@classmethod
def next_tanker_name(cls, country: Country, unit_type: AircraftType) -> str:
cls.number += 1
return "tanker|{}|{}|0|{}".format(country.id, cls.number, unit_type.variant_id)
@classmethod
def next_carrier_name(cls, country: Country) -> str:
cls.number += 1
return "carrier|{}|{}|0|".format(country.id, cls.number)
@classmethod
def next_convoy_name(cls) -> str:
cls.convoy_number += 1
return f"Convoy {cls.convoy_number:03}"
@classmethod
def next_cargo_ship_name(cls) -> str:
cls.cargo_ship_number += 1
return f"Cargo Ship {cls.cargo_ship_number:03}"
@classmethod
def next_jtac_name(cls) -> str:
name = (
ALPHA_MILITARY[cls.jtac_number]
if cls.jtac_number < len(ALPHA_MILITARY)
else str(cls.jtac_number + 1)
)
cls.jtac_number += 1
return f"JTAC {name}"
@classmethod
def random_objective_name(cls) -> str:
if cls.animals:
animal = random.choice(cls.animals)
cls.animals.remove(animal)
return animal
for _ in range(10):
alpha = random.choice(ALPHA_MILITARY).upper()
number = random.randint(0, 100)
alpha_mil_name = f"{alpha} #{number:02}"
if alpha_mil_name not in cls.existing_alphas:
cls.existing_alphas.append(alpha_mil_name)
return alpha_mil_name
# At this point, give up trying - something has gone wrong and we haven't been
# able to make a new name in 10 tries. We'll just make a longer name using the
# current unix epoch in nanoseconds. That should be unique... right?
last_chance_name = alpha_mil_name + str(time.time_ns())
cls.existing_alphas.append(last_chance_name)
return last_chance_name
namegen = NameGenerator