Feature/stuetzpunkt handel spieler - #41
Merged
Merged
Conversation
Das Push-Release erzeugte ein falsches Tag (3.19.0 statt 3.46.0), weil der Workflow fuer Tag und Changelog-Link den Output assembly-version (<AssemblyVersion> = 3.19.0) nutzte, waehrend das NuGet-Paket aus <Version> = 3.46.0 gepackt wird. - main.yml: Tag und Changelog-Link nutzen jetzt den Output "version" (entspricht <Version>, also der Paketversion). - csproj: AssemblyVersion und FileVersion auf 3.46.0 an <Version> angeglichen (waren seit 3.19.0 nicht mehr mitgezogen worden). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
KaufangebotAbgeben unterstuetzt jetzt auch menschliche Besitzer: der Betrag wird beim Anbieter reserviert und am Stuetzpunkt vermerkt (AngebotVonSpielerID/AngebotPreis). Neue Stuetzpunkt.AngebotVorlegen legt das Angebot dem Besitzer vor (Annahme: Besitzwechsel gegen Preis + Handelszertifikat Stufe 3; Ablehnung: Rueckerstattung). Manager: VerarbeiteEingehendeKaufangebote + StehenKaufangeboteAn fuer den Aufruf zu Zugbeginn. Nebenbei behoben: NameBesitzer im Bestaetigungstext nutzte faelschlich den aktiven Spieler statt den Stuetzpunkt-Besitzer. Verifiziert per Konsolentest (Angebot reserviert, Annahme uebertraegt und zahlt, Ablehnung erstattet zurueck). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Anbieter erhaelt zu Beginn seines naechsten Zuges eine eigene Meldung, ob sein Kaufangebot angenommen (Besitzwechsel) oder abgelehnt (Rueckerstattung) wurde. Neue spielstandskompatible, lazy initialisierte HumSpieler.HandelsNachrichten und SoeldnerRaeuberManager.ZeigeHandelsnachrichten; AngebotVorlegen reiht die Meldung beim Anbieter ein. Verifiziert per Konsolentest (Annahme- und Ablehnungs-Meldung kommen an und werden nach Anzeige geleert). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…9.0) Stuetzpunkt.ZumVerkaufAngeboten kennzeichnet einen zum Verkauf angebotenen Stuetzpunkt. SoeldnerRaeuberManager.GeneriereKiKaufangebote erzeugt zu Zugbeginn gelegentlich ein zufaelliges KI-Angebot (Preis um den aktuellen Wert). AngebotVorlegen verarbeitet jetzt auch KI-Anbieter: Annahme -> Besitzwechsel zur KI gegen Bezahlung (Flag zurueckgesetzt), Ablehnung -> bleibt gelistet, keine Rueckerstattung. Zusaetzlich SetzeZumVerkauf/IstZumVerkaufAngeboten sowie StuetzpunktVerwaltenManager.ZumVerkaufAngeboten fuer die UI. Verifiziert per Konsolentest (anbieten -> KI-Angebot -> Annahme uebertraegt und zahlt; Ablehnung bleibt gelistet). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die in der Abrechnung an menschliche Zollburg-Besitzer ausgezahlten Zoelle werden jetzt in HumSpieler.ZolleinnahmenGesammelt summiert (ZahleZollAusUndSammle) und dem Spieler zu Zugbeginn ueber SoeldnerRaeuberManager.ZeigeZolleinnahmen als Einnahme gemeldet, danach zurueckgesetzt. Verifiziert per Konsolentest (keine Meldung bei 0, Meldung + Reset bei gesammelten Zoellen). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neue Spieleinstellungen.KiAktivitaetProzent (1-100, Standard 50) steuert die Aktivitaet der KI in den Militaerstuetzpunkten. Raeuberlager und Zollburg leiten den Aktivitaetsfaktor direkt daraus ab (Prozent/50, also 50% = Faktor 1.0 wie bisher); alte Spielstaende (0) werden wie 50% behandelt. Die bisherige 3-Stufen-Auswertung (AggressivitaetKISpieler) entfaellt in beiden Klassen. Verifiziert: Lib-Build 0 Fehler. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…52.0) Stuetzpunkt.MoralBonusZahlen bezahlt vor dem Kampf einen einmaligen Moral-Bonus (Kosten je Truppenstaerke, gespeichert in MoralBonusBezahlt). MoralFuerKampf liefert die effektive Kampfmoral (Truppenmoral + MoralBonusWert 15, auf 100 gedeckelt) und wird im Kampfaufbau (Kampfberechnung) fuer die Angreifer genutzt. Der KampfereignisseManager erstattet den Bonus bei Sieg zurueck (bzw. ungenutzte Boni) und setzt ihn zurueck. Convenience am StuetzpunktVerwaltenManager fuer die UI. Verifiziert per Konsolentest (Boost-Math inkl. Deckelung, Bezahlen mit/ohne Truppen, Doppel-Bezahlung abgelehnt). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Auf Wunsch: Ein vor dem Kampf bezahlter Moral-Bonus wird mit dem Kampf verbraucht und bei einem Sieg nicht mehr zurueckerstattet (zuvor Rueckerstattung bei Sieg). Nur ein ungenutzter Bonus (ohne stattgefundenen Kampf) wird weiterhin erstattet. Bestaetigungstext angepasst (kein Rueckerstattungs-Versprechen mehr). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
….54.0) TruppenAnheuern bezahlt jetzt den Werbe-Etat und reiht die Truppen in Stuetzpunkt.GeworbeneTruppen ein, statt sie sofort per ErhoeheTruppen einzustellen. GeworbeneTruppenEinstellen stellt sie zum Rundenende ein (im KampfereignisseManager vor den Kaempfen, mit Meldung). GetAnzahlTruppenInklGeworben liefert stationierte + angeworbene Truppen fuer die Verwaltung. TruppenEntlassen storniert zunaechst noch nicht eingetroffene Anwerbungen und erstattet den Werbe-Etat zurueck. Kapazitaetspruefung inkl. angeworbener Truppen. Verifiziert per Konsolentest (Anwerben queuet + zahlt, Anzeige current+geworben, Stornierung erstattet zurueck, Rundenende stellt ein). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
KampfereignisseManager.ErmittleEreignisse erhaelt zwei Flags (aus dem WinForms-Original frmKampfereignisse uebernommen): KI-Stuetzpunkt- Aktionsmeldungen ausblenden und Kaempfe ohne menschliche Beteiligung (Angreifer/Verteidiger/ueberfallene Karawane alle KI) unterdruecken. Aktionen und Kaempfe werden weiterhin immer abgewickelt, nur die Anzeige wird gefiltert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
"Truppen schicken" mit gegnerischem Stuetzpunkt als Ziel erzeugt zum Rundenende einen Kampf (EnumKampfArt.StuetzpunktAngriff). Bei Sieg mit vollstaendig ausgeloeschter Garnison und ueberlebenden Angreifern wird der Stuetzpunkt eingenommen, sonst nur beschaedigt (-25 Zustand). KI greift je nach Aktivitaet ebenfalls an. Angriffe erst 7 Jahre nach Spielbeginn. Fehlerbehebung: invertierte Bereichspruefung im ZielStuetzpunktID-Setter verwarf zuvor jedes gueltige Ziel, sodass "Truppen schicken" nie ein Ziel speichern konnte. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die KI-Zielauswahl (KiZufaelligesAngriffsziel) beruecksichtigt nur noch Stuetzpunkte menschlicher Besitzer. Zusaetzlich ueberspringt ErmittleStattfindendeKaempfe als Sicherung jeden Angriff, bei dem Angreifer und Verteidiger beide KI sind (schuetzt auch alte Spielstaende). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ist der handelnde Spieler zollfrei (Privileg 23 bzw. 50%-Chance von Privileg 31), erhalten nun auch die Zollburg-Besitzer keinen Zollanteil mehr. Die Zollfreiheit wird vor der Auszahlung ermittelt und ueberspringt die gesamte Zollberechnung, statt die Kosten erst nachtraeglich auf 0 zu setzen (der Besitzer wurde zuvor trotzdem gutgeschrieben). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
KampfereignisseManager.ErmittleEreignisse entfernt die |-Marker um die Spielernamen nicht mehr aus den Kampf-Zusammenfassungen. Die Marker sind die Markup-Konvention der Lib und bleiben nun erhalten, damit die Ansicht die Namen hervorheben kann (fett, menschliche Spieler dunkelrot - wie im WinForms-Original). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die KI-Kandidatensuche in WahlAnlegen ignorierte nach 100 erfolglosen Versuchen die Eignungspruefung komplett - dadurch konnten z. B. amtslose Spieler fuer den Regenten kandidieren. Neu gibt es eine gelockerte Zwischenstufe (CheckBewerbAmtGelockert): der starre 1-2-Stufen-Sprung entfaellt, der Kandidat muss aber unterhalb des Zielamts liegen, und Amtslose bleiben auf Einstiegsaemter (Stufe 1-2) beschraenkt. Erst als allerletzte Reserve wird wie zuvor die Pruefung ignoriert, damit jede Wahl garantiert zwei Kandidaten hat. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Menschliche Spieler koennen sich jetzt gleichzeitig fuer mehrere freie Aemter bewerben. Massgeblich ist die Kandidatenliste der Wahl statt einer einzelnen gespeicherten Teilnahme; WahlAnmeldungUmschalten schaltet je Wahl unabhaengig um, GetBewerbungsangebote markiert alle Bewerbungen. Bei der Auszaehlung sortiert GetWahlenMitMenschlicherBeteiligung nach Amtsstufe absteigend (hoechstes Amt zuerst). Gewinnt der Spieler ein Amt, zieht VergebeAmt ueber die neue SpielerAusAllenWahlenEntfernen alle uebrigen Bewerbungen des Gewinners zurueck - er behaelt nur das hoechste gewonnene Amt. Kerkerstrafe und Ausscheiden entfernen den Spieler ebenfalls aus allen Wahlen. HatMenschlicheBeteiligung ist oeffentlich. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Issue #18, Schritt 1: Klagt ein menschlicher Spieler einen KI-Spieler an, beruecksichtigen die KI-Richter jetzt die von seinen Spionen gesammelten Beweise gegen den Angeklagten. StarteVerhandlung ermittelt die Beweisstaerke aus den Spionage-Delikten des Klaegers (GetBeweise), BerechneKiUrteil addiert sie zum Schuld-Faktor - mehr Beweise erhoehen die Verurteilungswahrscheinlichkeit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Issue #18, Schritt 2 (Mischung): KI begehen zum Rundenende zufaellige Delikte, deren Haeufigkeit mit der Bosheit steigt (RundenEndeManager.FuehreKiStraftatenDurch); die Verbrechen werden je Gesetz gespeichert und verblassen jaehrlich. Der Speicher begingVerbrechenX wurde von HumSpieler in die Basisklasse Spieler gehoben (KI + Mensch teilen ihn, additiv fuer kuenftige reale KI-Aktionen). StarteVerhandlung nutzt fuer KI wie Mensch die tatsaechlich begangenen Delikte statt Zufall; nach der Verhandlung sind sie gesuehnt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der in 3.63.0 in die Basisklasse Spieler gehobene Delikt-Speicher _begingVerbrechenX war bei per Deserialisierung geladenen Spielern null (der Konstruktor wird dabei umgangen), wodurch FuehreKiStraftatenDurch zum Rundenende crashte und das Jahr stehenblieb. Zugriff jetzt null-sicher per Lazy-Init. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ist der Spieler angeklagt, kann er eine Aussage waehlen (Leugnen, empoert leugnen, Teilgestaendnis, Gestaendnis; GetAussageOptionen / SetzeAussage). Gestaffelte Wirkung abhaengig von der Beweislage: Gestaendnis erhoeht die Verurteilungsneigung, senkt aber die Strafe (Straffaktor); Leugnen hilft nur bei schwacher Lage, empoertes Leugnen schlaegt bei starker Lage ins Gegenteil um. BerechneKiUrteil nutzt den Aussage-Bonus, WerteAus skaliert das Strafmass. IstAngeklagterAktiverSpieler steuert die Anzeige im Client. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Jedes Beweisstueck (begangenes Delikt bzw. erspaehtes Delikt) wog bisher nur 1 gegen die zufaellige Richter-Sympathie (20-80), sodass selbst bei klarer Beweislage kaum verurteilt wurde. Jedes Beweisstueck wird nun mit BeweisGewicht (10) gewichtet: echte Beweise fuehren im Schnitt zu ~80 % zur Verurteilung, gestaffelt nach Anzahl (0->5%, 1->31%, 2->63%, 3->84%, 4+->95%+). Die Aussage-Boni des Angeklagten wurden auf denselben Massstab angehoben, damit sie spuerbar bleiben (Gestaendnis fast sichere Verurteilung bei milderer Strafe, Leugnen raeumt Falschanklage frei, empoertes Leugnen schlaegt bei erdrueckender Lage ins Gegenteil um). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ist der aktive Spieler Partei, kann er vor dem Urteil die Richter bestechen: als Angeklagter auf Freispruch, als Klaeger auf Verurteilung (KannBestechen, GetRichterBestechungsOptionen, SetzeRichterBestechung). Wirkung "ab Schwelle sicher": erreicht der auf einen Richter entfallende Anteil dessen Schwelle (halbes Barvermoegen, mind. 3000), stimmt er sicher im Sinne des Bestechers, darunter anteilig (BerechneKiUrteil). Stufen sind auf das Barvermoegen begrenzt und werden sofort abgebucht; WurdeBestochen/GetBestechungsOffenlegung legen vor dem Urteil offen, dass Gelder geflossen sind. Der Zeugen-Topf (SetzeZeugenBestechung) ist angelegt, bleibt aber wirkungslos bis zu den echten Zeugen (Schritt 5). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
In jeder Verhandlung sagen bis zu zwei KI-Zeugen (weder Partei noch Richter) aus. Ob fuer oder gegen den Angeklagten ergibt sich aus dem Verhaeltnis (naeher am Angeklagten -> fuer ihn, sonst dagegen); ueberzeugend bei grossem Beziehungsunterschied, sonst schwach. Die Aussagen fliessen als _zeugenBonus ins Urteil (BerechneKiUrteil). Der in 3.66.0 angelegte Zeugen-Topf wirkt nun: Bestechung zieht einen Zeugen (ab Schwelle sicher) auf die Seite des Bestechers und laesst ihn ueberzeugend auftreten. Neu: GetZeugenAnzahl, ErmittleZeugenAussagen (nach der Bestechung), Klasse ZeugenAussage. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Zeugen tragen zusaetzlich zu ihrer Einordnung einen gesprochenen Satz vor, passend zu Richtung (fuer/gegen) und Ueberzeugungskraft (ueberzeugend/zoegerlich). Pronomen und der/die Taeter(in) richten sich nach dem Geschlecht des Angeklagten. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der JSON-Typ-Binder liess beim Laden nur "Conspiratio.Lib.*"-Typen zu und
wies die Kampf-Einheiten ab, die aus Kompatibilitaetsgruenden bewusst im
alten Namespace "Conspiratio.Kampf" verblieben sind (ZollSoeldner,
RaubRaeuber, ...). Dadurch war jeder Spielstand mit Stuetzpunkt-Einheiten
unladbar ("Error resolving type specified in JSON ...").
Der Binder loest Typen jetzt direkt in der Conspiratio.Lib-Assembly auf
(deckt den Kompatibilitaets-Namespace mit ab), nutzt die
Uebersetzungstabelle nur noch als Fallback fuer umbenannte Typen und
prueft weiterhin auf das "Conspiratio."-Praefix. Die Mapping-Tabelle
wurde zur gemeinsamen Nutzung durch beide Binder statisch gemacht.
Verifiziert gegen echte Spielstaende (test_godot_1606/1609).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Anklage- und Verteidigungsplaedoyer (GetAnklageplaedoyer, GetVerteidigungsplaedoyer). Anklage: Ton nach Beweislast (haltlos -> erdrueckend). Verteidigung: Ton nach Ansehen des Angeklagten; hohes Ansehen zieht die Richter zudem etwas Richtung Freispruch (_plaedoyerBonus in StarteVerhandlung, in BerechneKiUrteil: >=80 -6, >=30 -3). Schliesst die Gerichtsverhandlung-Erweiterung (Issue #18) ab. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…3.68.1) Das Rueckzahlungsjahr wurde als Restlaufzeit + aktuelles Jahr berechnet, die Restlaufzeit aber nie heruntergezaehlt -> das Jahr wanderte jedes Jahr mit (nach einem Schuldturm-Jahr sogar +2). Kredit bekommt ein festes _rueckzahlungsjahr, das NimmKredit auf aktuelles Jahr + Laufzeit setzt; GetOffeneKredite zeigt es an und schreibt alte Kredite (ohne festes Jahr) beim ersten Oeffnen einmalig aus der Restlaufzeit fest. TilgeKredit setzt es zurueck. Verifiziert per Konsolentest (Endjahr bleibt konstant). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neue Methode AemterManager.GetFreieAemterAnkuendigung() liefert die zu Zugbeginn neu zu besetzenden Aemter des aktiven Spielers als fertigen Ankuendigungstext (Amt + Ort je Zeile) bzw. null, wenn es keine fuer ihn bewerbbaren freien Aemter gibt. Basiert auf GetBewerbungsangebote. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…) (3.70.0) Neuer CheatManager fuer die komplexeren WinForms-Cheats: UebernehmeAmt (nimmt einer KI das Amt ab, tauscht das alte Amt zu ihr), BaueHaus, LasseVerklagen (Delikt + KI-Klaeger + drei Richter + Gerichtsverhandlung fuers Folgejahr). Dazu Combobox-Daten (Stufen/Gebiete/Aemter/Staedte/ Haustypen). Verifiziert per Konsolentest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die in der Statistik angezeigten, aber nie befuellten Kennzahlen werden jetzt waehrend des Spiels mitgezaehlt: verkaufte/eingekaufte Waren und Gesamtumsatz, entrichtete Steuern und Zoelle, Amtseinkommen, hoechstes Amt, Gesetzesverstoesse, Wahlteilnahmen/-siege, Anklagen, gezeugte Kinder und Schuldturm-Aufenthalte. Alle Zaehler betreffen nur menschliche Spieler. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neue Methode KontrahentenManager.GetKontrahentDetails(spielerId) samt Datenklasse KontrahentDetailInfo (Migration von KontrahentDetails): Name, Titel, Alter, Amt immer; Vermoegen, Gesundheit, Beweislast (per Spionage aufgedeckte Delikte) und Erhebungsstand nur bei laufender Spionage gegen den Kontrahenten. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…Anzeige Neues Modell Dynastiegeneration/AhnPerson + Ahnentafel-Liste am HumSpieler. FamilieManager.FuehreTestamentAus haelt die aktuelle Generation (Oberhaupt, Ehepartner, Kinder mit Jahren, Erbe) vor TestamentVollstrecken fest, sonst gingen die Daten bei der Erbuebernahme verloren. AhnentafelManager liefert alle Generationen (vergangene + lebende) fuer die Anzeige. PrivilegienManager fuehrt die Ahnentafel als immer verfuegbaren Eintrag. Savegame-kompatibel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
AhnPerson traegt jetzt den Titel. Oberhaupt und Ehepartner werden beim Erbfall und fuer die lebende Generation mit ihrem gegenderten Titel (GetTitelGegendert) erfasst; Kinder haben mangels Amt/Titel keinen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neuer GrabsteinManager.ErmittleGrabspruch(SpielerStatistik) schaetzt aus der Pro-Spiel-Statistik den praegendsten Typ des verstorbenen Charakters (Kriegsherr, Intrigant, Kaufmann, Kirchenmann, Staatsmann, Patriarch, Gesetzloser) und liefert einen passenden kurzen Grabspruch; ohne klares Profil einen allgemeinen. Vorbild "Die Fugger 2". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neuer MaetresseManager + HumSpieler.HatMaetresse. Ein verheirateter Spieler mit genug Talern kann sich eine Maetresse nehmen: einmalige Kosten, +Ansehen (dauerhaft), +verbleibende Jahre, geringere Chance auf ehelichen Nachwuchs (FamilieManager.StehtGeburtAn), jaehrlicher Unterhalt und Skandal-Risiko. PrivilegienManager fuehrt sie als synthetischen Eintrag, solange keine Maetresse vorhanden ist. Vorbild "Die Fugger 2". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neue Methode SchreibstubeManager.TilgeUeberfaelligeKredite() tilgt am Rundenende alle Kredite des aktiven Spielers, deren Rückzahlungsjahr erreicht oder überschritten ist – notfalls rutscht das Vermögen dabei ins Minus. Der Betrag wird dem Gläubiger gutgeschrieben, der Kredit-Slot geleert, und pro getilgtem Kredit wird eine Hinweismeldung zurückgegeben (mit gesondertem Hinweis, falls das Vermögen negativ wird). Fehlt bei Altspielständen das Rückzahlungsjahr, wird es aus Dauer + aktuellem Jahr nachgetragen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Über <DebugType>embedded</DebugType> werden die Debug-Symbole nun direkt in die Assembly eingebettet - auch im Release. Dadurch enthalten Stacktraces bei den Endnutzern Datei- und Zeilennummern, und die Symbole reisen im NuGet-Paket mit. Grundlage für aussagekräftige Fehlerberichte. Keine Code-Änderung, nur Build-Einstellung. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Optionale, bei der Spielerstellung wählbare Aufträge nach Vorbild von "Die Fugger 2", unterteilt in leicht/mittel/schwer. - EnumAuftrag + Spieleinstellungen.Auftrag (Standard KeinAuftrag = freies/endloses Spiel; savegame-sicher). - AuftragManager: sieben Aufträge (Aufsteiger, Kleiner Wohlstand, Herr des Doms, Mäzen, Baumeister, Talerrennen, Kriegsherr) mit Fortschritts- und Erfüllungsprüfung sowie Fortschrittstext. - HighscoreManager: lokale Bestenliste (highscores.json), sortiert nach Schnelligkeit (wenigste Spieljahre zuerst). - HumSpieler: neue Zähler DomherrJahreInFolge und GestifteterBauwert; BauwerkStiftenManager.FuehreStiftungAus addiert den gestifteten Wert mit (für "Mäzen"). Alte Spielstände starten ohne Auftrag, Zähler 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Erweitert den AuftragManager um sechs Aufträge (jetzt 13 gesamt): - leicht: Kaufmann (200.000 Taler Gesamtumsatz), Familienvater (3 Kinder) - mittel: Wahlsieger (3 Wahlen gewinnen), Kriegsheld (10 Kämpfe gewinnen) - schwer: Karawanenschreck (8 Karawanen überfallen), Meuchelmörder (3 erfolgreiche Anschläge) Alle nutzen bereits geführte SpielerStatistik-Kennzahlen; kein neues Tracking nötig. Die neuen EnumAuftrag-Werte sind ans Ende angehängt, sodass bestehende Enum-Werte und damit alte Spielstände stabil bleiben. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nfassen Alle Änderungen seit dem letzten echten GitHub-Release (3.46.0) stehen jetzt gesammelt unter einer einzigen ## [Unreleased]-Überschrift (DE- und EN-Stichpunkte), statt je Change einen eigenen datierten Versionsblock. Künftige Changes werden nur noch dort angehängt; die csproj-Version darf weiterhin erhöht werden. 3.46.0 und älter bleiben unverändert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GetFreieAemterFuerSpX schrieb die bewerbbaren Ämter in ein fest 50 Einträge großes Array, obwohl es bis zu 199 Wahlen geben kann. War ein Spieler für mehr als 50 gleichzeitig offene Ämter bewerbbar (z. B. wenn durch Todesfälle oder Sabotage viele Ämter auf einmal frei wurden), lief das Array über (IndexOutOfRangeException). Das Array wird nun auf die maximale Wahlenzahl dimensioniert; GetAnzahlFreieAemterFuerSpX zählt robust bis zum ersten Leereintrag. Behebt das alte 'gelegentlich viel zu hoher amtcounter, speziell wenn sabotiert wird'-TODO. Mit 60 bewerbbaren Ämtern reproduziert und verifiziert (vorher IndexOutOfRange, jetzt korrekt 60). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die Methode ZugNachrichtenManager.FuehreTodDesAktivenSpielersDurch wurde nirgends aufgerufen (Lib, Godot, WinForms) und trug ein veraltetes TODO zu Testament/Erbfolge – beides läuft längst über FamilieManager.FuehreTestamentAus. Ersatzlos entfernt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Das Kellermeister-Privileg (Amt 23) zeigte bisher nur einen Text ohne
Wirkung. Jetzt:
- PrivVergifteterWein.PrivExecute öffnet die Personen-Karte im
Zielauswahl-Modus 12 (sofern noch keine Vergiftung vorbereitet ist).
- KontrahentenManager.PersonWasMachen führt für Modus 12
SW.Dynamisch.WeinVergiften aus (5.000 Taler, Ziel für dieses Jahr
vormerken).
- AemterEbeneManager.GetTitel liefert die Kopfzeile "Wein vergiften in".
Auflösung (FuehreVergiftetenWeinDurch) und Erfolgschance waren bereits
vorhanden; die Ergebnismeldung grammatikalisch korrigiert
("... wieder, doch seine Gesundheit hat gelitten"). Mit Konsolentest
verifiziert (Zielvormerkung, Kosten, Doppelsperre, Auflösung, Reset).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GetUntergebene legte Untergebenen-Aemter/-Inhaber in zwei fest 7 Eintraege grossen Arrays ab; ufinalID multipliziert je untergeordnetem Amt ueber alle Staedte/Laender eines Gebiets. In der aktuellen Aemtertabelle passt das gerade so (max. 6 Eintraege) - der Puffer ist aber nur einen Slot gross, sodass ein zusaetzliches Unteramt oder eine 5. Stadt je Land eine IndexOutOfRangeException ausloesen wuerde. Arrays jetzt nach den Max-Konstanten dimensioniert (analog zum Wahlen-Fix). Analytisch verifiziert: max. moegliche Fuelllaenge ueber alle Aemter = 6, neue Groesse deutlich groesser; kein Regressions-Crash. Gefunden bei einem gezielten Scan nach fest verdrahteten Array-Groessen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tipps[16] war doppelt belegt: der Kredit-Hinweis ueberschrieb den Tipp "Verkaufserloes nimmt bei wiederholtem Verkauf ab", der dadurch nie angezeigt wurde. Der Kredit-Hinweis liegt jetzt auf Index 30, TippsMaxIndex entsprechend auf 30 erhoeht. Verifiziert: MaxIndex 30, Tipp 16 = Verkaufserloes, Tipp 30 = Kredit, keine leeren Tipps in 0..30. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neues Feature nach Vorbild "Die Fugger 2": - FechtDuellManager: Fechtunterricht (steigende Kosten, hebt die Fechtfaehigkeit) und Duelle. Ein Amtstraeger kann wegen einer Beleidigung zum Duell gefordert werden (max. eines pro Zug). Der Sieger ergibt sich aus der Fechtfaehigkeit gegen eine aus der KI-Bosheit abgeleitete Gegnerstaerke plus Zufall. Der Verlierer verliert Gesundheit; unter 30 verliert er sein Amt (AmtVonXfreigeben, Neuwahl) - symmetrisch, auch der Spieler kann verlieren. - HumSpieler: Fechtfaehigkeit, FechtstundenGenommen, DuellGefuehrtDiesesJahr (Reset in RundenManager.BeginneZug). - PrivilegienManager: synthetische Eintraege 10002 (Fechtunterricht) und 10003 (Duell). Personen-Karten-Modus 14 in KontrahentenManager und AemterEbeneManager. Mit Konsolentest verifiziert: Preisstaffel, Skill, Duell-Voraussetzungen, Sieg -> KI-Amtsverlust, Symmetrie (Spieler verliert -> eigenes Amt weg), Once-per-year-Sperre. Alte Spielstaende starten mit Fechtfaehigkeit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Beleidigung ist jetzt ein Ehrenhandel mit Entscheidung statt sofortigem Duell: - Beleidige(zielId): Der Beleidiger sinkt deutlich im Ansehen des Ziels (Beziehungsverlust bei KI). Der Beleidigte entscheidet ueber Satisfaktion (KI aus Bosheit, Mensch per Dialog). - VerweigereSatisfaktion(id): Verzicht kostet den Verzichtenden Ansehen bei den Amtstraegern seiner Amtsstufe (Stadt/Land/Reich). - PruefeKiBeleidigtSpieler(): Selten beleidigt eine KI den Spieler; die Chance haengt vor allem an der (feindseligsten) Beziehung zum Spieler und steigt erst unter "neutral" (50), Bosheit spielt eine kleine Rolle. Gedeckelt ~7-8 %, im Schnitt seltener als alle 15 Zuege. - Duell "im Morgengrauen"; Mensch-gegen-Mensch vergleicht beide Fechtfaehigkeiten. Privileg-Label "Amtstraeger beleidigen". Verifiziert: Beziehungsverlust -25, Ansehensverlust -15, Frequenz (Bez.60->0%, 30->3.1%, 0->6.8%), Mensch-Duell 96%/6%. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die Chance, dass eine beleidigte KI Satisfaktion (ein Duell) verlangt, steigt von 30 % + Bosheit/2 auf 50 % + Bosheit/2 (Bereich jetzt 50-100 %, vorher 30-80 %). Nur die Konstante KiSatisfaktionsBasis. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- PlayerSetupManager.ErstelleSpieler setzt das Alter der menschlichen Spieler passend zum Startjahr, sodass ihr Geburtsjahr 1580 ist (vorher blieb das Alter 0 -> Geburtsjahr = Startjahr). - FechtDuellManager.GetBeleidigungsFrage nutzt "Er"/"Sie" je nach Geschlecht des Ziels statt fest "Er". Verifiziert: Startjahr 1600 -> Alter 20, Geburtsjahr 1580; Frage maennl./weibl. korrekt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Damit der Client ein Duell als eigene Szene inszenieren kann, gibt es eine neue UI-Schnittstelle IDuellDialog (SW.UI.DuellDialog). Sie ist ein optionaler Parameter von UIHelper.Initialisieren, sodass Clients ohne Inszenierung unveraendert bleiben. DuellErgebnis liefert zusaetzlich GegnerName und AmtName, damit der Client den Ausgang selbst formulieren kann, statt die vorformulierte Meldung zu zerlegen. Verlangt ein Beleidigter Satisfaktion, spielt KontrahentenManager das Duell ueber den neuen Dialog aus; ist keiner registriert, bleibt es bei der bisherigen Textmeldung. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ein Duell wird nicht mehr ausgewuerfelt, sondern als Schlagabtausch von Beleidigungen gespielt (Vorbild "Monkey Island 1"). Der neue WortgefechtManager fuehrt je Wortwechsel zwei Schritte: Der Angreifer waehlt aus mindestens drei Beleidigungen, der Angegriffene muss unter mindestens drei Kontern den passenden erkennen. Die falschen Antworten sind die Konter anderer Beleidigungen und klingen darum absurd. Wer zuerst drei Wortwechsel gewinnt, gewinnt das Duell; kein Spruchpaar wiederholt sich. Gegen einen menschlichen Gegner waehlen beide Seiten selbst (Hot-Seat), gegen die KI entscheidet beim Kontern ein Wuerfel, gewichtet mit der Fechtfaehigkeit. Diese wirkt hybrid: gedeckelter Treffervorsprung plus haeufiger sitzende eigene Beleidigungen. Die Gewichte sind so kalibriert, dass perfektes Kontern gegen einen mittleren Gegner auch ganz ohne Fechtunterricht rund 70 % der Duelle gewinnt, waehrend durchweg falsche Konter selbst mit maximalem Unterricht nur rund 40 % gewinnen - Training hilft spuerbar, ersetzt den Witz aber nicht. Damit der Ausgang erst nach dem Gefecht feststeht, ist FechtDuellManager aufgetrennt: BerechneSiegchance und WendeDuellAusgangAn sind oeffentlich, FuehreDuellDurch (gewuerfeltes Duell) verhaelt sich unveraendert und bleibt der Weg fuer Clients ohne Inszenierung. IDuellDialog bietet nun SpieleWortgefecht und ZeigeAusgang. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die mit Spionen gesammelten Beweise lassen sich jetzt nutzen: Wer genug Belastendes gegen einen Amtstraeger hat, kann ihn erpressen und einige Jahre lang dessen Amtsprivilegien mitnutzen. Umsetzung nach dem Konzept von PommBaer samt der Abstimmung im Issue. Die Beweispunkte mussten nicht neu erfunden werden: AktiveSpionagen zaehlt nicht Vorfaelle, sondern summiert die Beweismaechtigkeit (1-4 je Fund) - genau die Groesse, die das Konzept meint. Noetig sind 3/5/7 Punkte je nach Amtsebene. Die Erfolgsaussicht betraegt 75 % plus 4 % je ueberzaehligem Punkt, minus 15 % je Titelstufe des Ziels ueber dem Erpresser (plus 3 % je Stufe darunter), minus 5 % bei gleicher Religion; die drei Szenarien der Konzept-Tabelle ergeben damit exakt 56/48/40 %. Eine gelungene Erpressung wirkt 4/3/2 Jahre plus 0-3/0-2/0-1 Zufall (im Issue gegenueber dem Konzept um ein Jahr gekuerzt) und verbraucht die Beweise; eine misslungene laesst sie verfallen. Mehrere Erpressungen laufen parallel und enden zum Jahreswechsel. Menschliche Opfer entscheiden selbst (neue Schnittstelle IErpressungDialog) - wer ablehnt, laesst dem Erpresser die Beweise fuer eine Anklage. Fuer die Privilegien-Uebernahme genuegte eine neue Abfrage: Die gesamte Amtsabhaengigkeit steckt in PrivilegienAktualisieren, die Privilegien selbst wirken generisch. GetAmtsPrivilegien spiegelt diese Bedingungen; ein Konsolentest vergleicht beide ueber alle Aemter, damit sie nicht auseinanderlaufen. Der Erpresste verliert die aktiv nutzbaren Amtsprivilegien und behaelt die passiven. Erpressung ist selbst strafbar. Das neue Strafgesetz brauchte entgegen der Befuerchtung keine Savegame-Migration: Die Gesetzestabelle hat 100 feste Plaetze und ist nur duenn belegt, sodass Index 25 im Strafblock frei war - Gericht und Jurist erfassen ihn ueber die vorhandenen Bereichsgrenzen von selbst. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bislang gab es nur im Godot-Repo eine Anleitung; die Lib-spezifischen Regeln mussten jedes Mal neu erlesen werden. Festgehalten sind vor allem die Dinge, die man dem Code nicht ansieht: - Sprachstand C# 7.3 (netstandard2.0 ohne LangVersion) als harte Grenze. - Das Rezept, eine unveroeffentlichte Version fuer den Godot-Client sichtbar zu machen - inklusive des Schritts, der immer wieder vergessen wird: ohne Loeschen im NuGet-Cache baut Godot stillschweigend gegen den alten Stand. - Savegame-Kompatibilitaet: Der ContractResolver erzeugt Objekte ohne Konstruktoraufruf, spaeter ergaenzte Felder kommen also als null bzw. zu kurzes Array an. Daraus folgt die Lazy-Init-Konvention. - Domaenen-Fallstricke, die in dieser Sitzung Zeit gekostet haben: Amt und Gebiet gehoeren zusammen, die Gesetzestabelle hat 100 feste Plaetze und ist duenn belegt, Spionage-Beweise sind eine Punktsumme statt eines Zaehlers, und die Amtsabhaengigkeit der Privilegien steckt an genau einer Stelle. - Testgewohnheiten: Zufallswerte fixieren, bei Wahrscheinlichkeiten auf Quoten statt Einzelfaelle pruefen, Refactorings gegen das Original vergleichen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die Spielregeln wurden bisher mit wegwerfbaren Konsolenskripten geprueft, die nach jedem Feature geloescht wurden - die Zusicherungen waren damit jedes Mal verloren. Sie leben nun als 36 Tests in Conspiratio.Lib.Tests weiter. Verankert sind unter anderem: die drei Szenarien der Erpressungs-Konzepttabelle als exakte Werte (56/48/40 %), Mindestbeweise und Wirkungsdauer je Amtsebene, der Beweisverfall inklusive der PvP-Sonderregel, parallel laufende Erpressungen, die Balance-Quoten des Wortgefechts, die Duellauswertung sowie die Lazy-Init-Zugriffe, von denen die Ladbarkeit alter Spielstaende abhaengt. Der wichtigste Test vergleicht GetAmtsPrivilegien mit PrivilegienAktualisieren ueber alle Aemter. Diese Gleichwertigkeit war die Grundlage der Privilegien-Uebernahme und ist nun gegen spaeteres Auseinanderlaufen abgesichert. Der gesamte Spielzustand liegt in statischen SW-Fassaden, deshalb laeuft die Suite bewusst ohne Parallelitaet und jeder Test baut sich seine Spielwelt neu auf. Zufallsabhaengige Groessen (KI-Bosheit) werden gepinnt, Wahrscheinliches wird ueber Quoten statt Einzelfaelle geprueft. Das Projekt ist nicht packbar und stoert die Pack- und Publish-Kette nicht; beide Workflows fuehren die Tests jetzt aus, im Release-Workflow bewusst vor dem Veroeffentlichen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Das Privileg blieb nach einem Amtswechsel sichtbar, wenn das neue Amt gar keine Untergebenen hat: In PrivilegienAktualisieren deckte die Zuweisung nur den Fall "Untergebene vorhanden" ab, sodass ein einmal gesetztes true aus einem frueheren Amt stehen blieb. Ein Klick zeigte dann eine leere Liste. Die Zuweisung erfasst jetzt beide Faelle. Der zugehoerige Test sucht sich die passenden Aemter selbst - je eines mit und ohne Untergebene - und bleibt damit gueltig, falls sich die Spieldaten aendern. Dass er den Fehler wirklich fasst, wurde geprueft, indem die Korrektur voruebergehend zurueckgenommen wurde: Dann schlaegt er fehl. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die READMEs (deutsch und englisch) bekommen einen Abschnitt "Tests": was es gibt, wie man es startet, und die Erwartung, dass neue Features ueblicherweise Tests mitbringen - inklusive der Abgrenzung, was keine braucht (reine Textausgaben, blosses Weiterreichen an die Oberflaeche). In der CLAUDE.md stand noch "There are no automated tests". Der Abschnitt ist nun zweigeteilt: die Tests als Normalfall samt der Konventionen, von denen die Suite abhaengt (keine Parallelitaet wegen des statischen SW-Zustands, TestSpielwelt-Helfer, gepinnte Zufallswerte, Quoten statt Einzelfaelle), und die Konsolen-Harness ausdruecklich als Werkzeug zum Umsehen statt zum Behalten. Neu festgehalten sind zwei Erkenntnisse: Bei einer Fehlerbehebung erst nachsehen, dass der Test ohne die Korrektur fehlschlaegt. Und: Das Veroeffentlichen auf nuget.org ist ein Nebeneffekt von master - solange etwas auf einem Feature-Branch liegt, existiert die Version fuer andere und fuer die CI nicht. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sturm, Flut, Brand, Erdbeben und Pest suchen die Staedte heim - selten, rund alle vier bis fuenf Jahre, dann aber heftig. Die Auswahl musste nicht erfunden werden: Jede Stadt traegt seit jeher je Art eine Anfaelligkeit von 0-100 in den Spieldaten (Stadt.GetKatastrophen), die bislang ungenutzt war. Art und Ort werden danach gewichtet ausgelost, und eine Stadt mit 0 wird von dieser Art nie getroffen - Hafenstaedte ersaufen, Bergstaedte beben. Eine Katastrophe trifft eine einzelne Stadt, alle anfaelligen Staedte einer Grafschaft oder des ganzen Reichs. Folgen je betroffener Stadt: 8-20 % der Einwohner (Pest doppelt), 1-2 Punkte Reichtum und 20-40 % der Warenvorraete; die Knappheit hebt die Preise um 2-4 je Ware. Ein echtes Angebot/Nachfrage-System gibt es nicht - die Preise schwanken sonst rein zufaellig und haengen nicht am Vorrat -, deshalb wirkt die Katastrophe direkt auf Vorrat und Preis statt auf eine simulierte Nachfrage. Auch die Spieler trifft es in betroffenen Staedten: eingelagerte Waren im selben Umfang, Wohnsitze verlieren 10-25 Prozentpunkte Zustand, und eine Pest kostet Gesundheit, wenn man dort wohnt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…7.0) SW.Statisch.SetRnd(int seed) setzt den Zufallsgenerator auf einen festen Startwert. Rnd war bisher nur lesbar, sodass sich ein Spielverlauf nicht wiederholen liess - ein fehlgeschlagener automatischer Durchlauf des Godot-Clients war damit nicht nachstellbar. Genau das hat sich sofort ausgezahlt: Mit festem Startwert war ein bis dahin sporadischer Haenger reproduzierbar und als echter Fehler zu erkennen. FuelleRestlicheAemter wuerfelte fuer jede angelegte Wahl blind einen der KI-Plaetze als Gewinner aus. IstDieWahlVoll besagt aber nur, dass die Wahl angelegt ist - nicht, dass sich jemand beworben hat. Traf der Wuerfel einen leeren Platz (Kandidat 0), scheiterte VergebeAmt mit einer NullReferenceException, die den gesamten Jahreswechsel abbrach und das Spiel haengen liess. Gewaehlt wird jetzt nur unter den tatsaechlich vorhandenen Bewerbern; gibt es keinen, bleibt das Amt unbesetzt und die Wahl steht im naechsten Jahr erneut an. Tests: TestSpielwelt.Starte nimmt einen optionalen Startwert, ZufallTests sichern die Reproduzierbarkeit (gleiche Zahlenfolge und gleicher Spielaufbau), AemterTests decken die Wahl ohne Bewerber und den einzelnen Bewerber ab. 51 Tests gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.