# generate_manifests.py # Fortel Trappa — pełne manifesty ładunkowe (HOLD I/II/III) w ZIP # Uruchom: python generate_manifests.py -> powstaną dwa pliki ZIP w bieżącym katalogu. import random, zipfile, datetime random.seed(40000) # deterministyczny „smak” WORLDS = ["Ostia","Avachrus","Enoch","Gilead Prime","Nethreus","Ryza","Vostroya","Scintilla","Footfall"] INN_NOTES = [ "Zwykły wyrób, zgodny z normą diecezjalną.", "Do użytku cywilnego; dokumentacja pełna.", "Na potrzeby konserwacji/edukacji polowej.", "Brak zasilania, brak funkcji specjalnych.", "Wersja eksportowa; gwinty zgodne z PL-3.", "Na morale i porządek; bez cech bojowych.", "Próbki kontrolne — wynik negatywny na scrapcode.", "Rekwizyty katechetyczne; brak statusu kultowego.", "Puste, czyste, opieczętowane.", "Zabezpieczone audytem Ministorum.", "Składane; bez ostrych krawędzi w papierach.", "Zwykła jakość magazynowa; brak niespodzianek.", "Brak reakcji psionicznej (pomiar: tło).", "Standard przemysłowy; kompatybilność wysoka.", "Do ekspozycji; nieotwierane przy inspekcji.", "Zestaw muzealny; kojąco nudny.", "Oznaczenie ‘cywilne’; instrukcja w komplecie.", "Zgodne z przepisem P-77 (ładownie ogólne).", "Pieczęć diecezjalna aktualna; datowanie bieżące.", "Bezpieczne dla chóru i czytników vox." ] INN_NAMES = [ "Ziarno kultywacyjne ‘Święty Oset’","Mąka ‘Hostia’","Kasza jęczmienna ‘Pielgrzym’","Groch ‘Kocioł’","Fasola ‘Pilgrim’", "Sól żywnościowa","Olej lampowy","Smary maszynowe ‘Stałość’","Farba kadłubowa ‘Mgła’","Pasy mocujące ‘Ordo Cargo’", "Złącza heksowe","Zawory nadciśnieniowe","Łożyska baryłkowe ‘Wytrwałość’","Łożyska kulkowe precyzyjne", "Taśmy stalowe ‘Krzyżowe’","Plandeki światłochłonne ‘Cień’","Pudła ciszy (obudowy wygłuszające)","Lampiony procesyjne", "Witraże polowe (składane)","Zwoje pergaminowe ‘Sztywna Karta’","Maski nabożne ‘Neutral’","Relikwie podręczne (skrzynki)", "Szkatuły dewocyjne (stal miękka)","Szkła ochronne ‘Błękit Służbowy’","Barwniki okienne (błękit/purpura)", "Kity hermetyczne ‘Głuchy Spaw’","Rury segmentowe PL-7","Kable PL-3 ‘Uniwersalne’","Siatki zabezpieczające ‘Drobne Oczko’", "Zasuwy grodziowe PL-10","Zaczepy stalowe ‘Cierpliwość’","Kątowniki ciężkie ‘Prosto’","Nity kadłubowe ‘Amen’", "Skrzynki na dźwięk (wygłuszenie)","Szkła różnobarwne (mix)","Amfory gliniane ‘E-Seria’","Szaty ‘Pokora’ (robocze)", "Kopułki modlitewne (mini)","Płaszcze przeciwdeszczowe ‘Wachta’","Świece czarne ‘Negocjacje’","Świece woskowe ‘Cisza Nocna’", "Zwoje kabli heksowych (ekranowane)","Sprężyny powrotne","Zawiesia wielokrążkowe","Przekaźniki proste ‘Miedź’", "Łożyska stożkowe ‘Kierunek’","Szkatuły na krople (apteczne)","Ołtarze polowe (składane)","Figurki pobożne", "Piety miniaturowe","Popiół posypny (liturgiczny)","Kleje statkowe ‘Głuchy Spaw’","Klemy zasilające ‘Moc’", "Kołnierze izolacyjne PL-5","Beczki puste ‘Gotowość’","Rolki transportowe ‘Gładkie’","Słód jasny ‘Nocny’", "Skrzydła drzwiowe ‘Jedność’","Skarbonki parafialne","Księgi wizualne (albumy)","Zegary harmoniczne (niski ton)", "Baldachimy małe ‘Krem’","Puchar kapłański (rekwizyt)","Księgi zakładkowe","Pasy transmisyjne ‘Ciągłość’", "Pudła akustyczne (puste)","Rękawice robocze ‘Skóra+’", ] XENO_REAL = [ "fragmenty wraithbone Aeldari (martwe, obrobione ‘na szkło’)", "odpryski spirit-stone (pozbawione ładunku)", "ukryty vox-scrambler xeno (obudowa cywilna)", "mikrofiolki po jadu Lhamaean (dokładnie wyparzone)", "moduł holo-emisyjny Aeldari (matryca wycięta, nieaktywny)", "kaseta rozliczeń cold trade (podwójne dno)", "nekrotech — fragment stele ‘bezcielesnej’ (kamień ‘ozdobny’)", "obudowy tłumiące sygnał (technologia nieidentyfikowana)", "orb psioniczny — tłumik nastroju (źródło Aeldari)", "halo-device: element oprawy (niekompletne, bez rdzenia)", "resztki proscribed tomes (okładki, wkład wymieniony na blanki)", "zegar-pikietaż dla transakcji cold trade (ukryty znacznik czasu)", "ampułki po obscura klasy ceremonialnej (umyte; testy czyste)", "fiolki po ‘ichorze’ drukhari (sterylnie czyste)", "masker polowy Drukhari — tkanina z włóknem ziggurat (zdezaktywowana)", ] def inn_note(): return random.choice(INN_NOTES) def name(): return random.choice(INN_NAMES) def world(): return random.choice(WORLDS) def qty(): return random.randint(1, 8) def make_line(idx, suspicious_ratio=0.34): q = qty(); nm = name(); ow = world(); note = inn_note() if random.random() < suspicious_ratio: paren = f"({random.choice(XENO_REAL)})" else: paren = f"({random.choice(['zwykły ładunek cywilny','materiały szkoleniowe/rekonstrukcja','zestaw konserwatorski','komplet części serwisowych','puste i czyste','standard magazynowy','produkt spożywczy','wyposażenie pomocnicze','materiały dekoracyjne','narzędzia warsztatowe'])})" return f"{idx}) {q}× — {nm} — {ow} — [{note}] {paren}", q def make_section_text(hold_label, s_idx, s_cnt): header = f"=== FORTEL TRAPPA — MANIFEST ŁADUNKOWY ===\n{hold_label} / SEKCJA {s_idx} z {s_cnt}\n(Format: [Liczba 1–10] × Standardowy Imperialny Kontener — Nazwa — Pochodzenie — [Uwaga kapitańska] (co to naprawdę jest))\n\n" total = 0; entries = [] for i in range(1, 124): line, q = make_line(i, suspicious_ratio=0.34) entries.append([line, q]); total += q if total > 1000: excess = total - 1000 for i in range(len(entries)-1, -1, -1): if excess <= 0: break q = entries[i][1] if q > 1: red = min(q-1, excess); entries[i][1] -= red; excess -= red prefix, rest = entries[i][0].split("× —", 1) idx_str = prefix.split(")")[0] + ")" entries[i][0] = f"{idx_str} {entries[i][1]}× —{rest}" body = "\n".join(e[0] for e in entries) footer = f"\n\n— KONIEC: {hold_label} / SEKCJA {s_idx}/{s_cnt} —" return header + body + footer def write_full_zip(path_full, path_hold1): with zipfile.ZipFile(path_full, "w", compression=zipfile.ZIP_DEFLATED) as z: for s in range(4, 17): # HOLD I 04–16 z.writestr(f"HOLD_I_SEKCJA_{s:02d}.txt", make_section_text("HOLD I", s, 16)) for s in range(1, 16): # HOLD II 01–15 z.writestr(f"HOLD_II_SEKCJA_{s:02d}.txt", make_section_text("HOLD II", s, 15)) for s in range(1, 16): # HOLD III 01–15 z.writestr(f"HOLD_III_SEKCJA_{s:02d}.txt", make_section_text("HOLD III", s, 15)) z.writestr("README.txt", f"FORTEL TRAPPA — MANIFESTY ({datetime.datetime.utcnow().isoformat()}Z)\nHOLD I: 04–16; HOLD II: 01–15; HOLD III: 01–15\n~1/3 pozycji w ( ) ma real-tożsamość (xeno/kontrabanda), [ ] — noty ‘urzędowo niewinne’.\n") with zipfile.ZipFile(path_hold1, "w", compression=zipfile.ZIP_DEFLATED) as z: for s in range(4, 17): z.writestr(f"HOLD_I_SEKCJA_{s:02d}.txt", make_section_text("HOLD I", s, 16)) z.writestr("README_HOLD_I.txt", f"HOLD I (04–16) — {datetime.datetime.utcnow().isoformat()}Z\n") if __name__ == "__main__": write_full_zip("FORTEL_HOLD_I_II_III_MANIFESTS.zip", "FORTEL_HOLD_I_SEKCJE_04-16.zip") print("OK: FORTEL_HOLD_I_II_III_MANIFESTS.zip | FORTEL_HOLD_I_SEKCJE_04-16.zip")