Support Advanced native Homeworld return
Verify and publish checkpoint container / container (push) Successful in 11m10s

This commit is contained in:
Quintine committed 2026-10-29 04:48:47 +11:00
1 parent 1cf90f1328
commit 89569e92a1
14 files changed
+429 -39

No files matched your search

+11 -3
View File
@@ -31921,7 +31921,11 @@ function findLegalBattlePlan(
for (let source = 0; source < (nativeFee ? nativeSources?.length ?? 0 : 1); source++) {
for (const n of numerical) {
const candidate: Partial<Plan> = { ...partial, ...n };
if (nativeFee) candidate.reinforcementsSources = nativeSources![source];
if (nativeFee) {
candidate.reinforcementsSources = nativeSources![source];
candidate.reinforcementsElite = Object.values(candidate.reinforcementsSources)
.reduce((sum, forces) => sum + forces.elite, 0);
}
if (!accepts(candidate)) continue;
try {
return validatePlan(g, p, candidate, promises);
@@ -31931,6 +31935,7 @@ function findLegalBattlePlan(
if (alternateSpecial) {
candidate.planetologistSpecial = true;
delete candidate.reinforcementsSources;
delete candidate.reinforcementsElite;
try {
return validatePlan(g, p, candidate, promises);
} catch (error) {
@@ -38416,9 +38421,12 @@ function declareHomeworldShipment(g: Game, p: Player, intent: HomeworldShipmentI
} else continueHomeworldShipment(g, shipment);
}
function homeworldUsesGuildTransport(g: Game,
shipment: HomeworldShipmentIntent & {route?: 'arrakis'}): boolean {
shipment: HomeworldShipmentIntent & {route?: 'arrakis'; guildTransportEvent?: string}): boolean {
// The revised Advanced rules grant World-to-World transport to every
// faction. Preserve already-open native Guild permission windows in saves.
return getPlayer(g, shipment.player).faction === 'guild' &&
(shipment.route === 'arrakis' || shipment.destination === 'homeworld:guild');
(shipment.route === 'arrakis' || shipment.destination === 'homeworld:guild' &&
(!g.advanced || !!shipment.guildTransportEvent));
}
function continueHomeworldShipment(g: Game, shipment: PendingHomeworldShipment) {
if (!openHomeworldTransportPermission(g, shipment) && !openHomeworldGuildRate(g, shipment))
+5 -9
View File
@@ -147,7 +147,7 @@ export function homeworldShipmentChoice(
return result;
}
if (
view.guildTransportCanceled &&
!view.advanced && view.guildTransportCanceled &&
me.faction === 'guild' &&
destination === 'homeworld:guild'
) {
@@ -266,9 +266,9 @@ export function homeworldShipmentActions(
const targets = worlds
.filter(
(world) =>
(world.native !== me.id || me.faction === 'guild') &&
(view.advanced || world.native !== me.id || me.faction === 'guild') &&
!(
view.guildTransportCanceled &&
!view.advanced && view.guildTransportCanceled &&
me.faction === 'guild' &&
world.native === me.id
) &&
@@ -306,12 +306,8 @@ export function homeworldShipmentActions(
sourceGroups.push(imperial);
const actions: Action[] = [];
for (const target of targets) {
if (
target.world.native === me.id &&
target.world.side === 'high' &&
target.strength === 0
)
continue;
if (!view.advanced && target.world.native === me.id &&
target.world.side === 'high' && target.strength === 0) continue;
const required = Math.max(
1,
target.strength + [0, 1, 2, 3][difficulty] - target.existing,
+6 -5
View File
@@ -35,9 +35,10 @@ function requireShipment(
}
/** E3 world-to-world transport: use the actual native or foreign source pool.
* Guild may also return a foreign garrison to its own world; other own-world
* exceptions need separately established permission. The caller owns timing, usage,
* funding, bank payment, responses and arrival effects. A purchased ordinary
* Basic preserves the printed own-World return restriction; the user-authorized
* Advanced revision (physical p.22) permits travel between distinct Homeworlds,
* including an actual foreign garrison returning to its own World. The caller
* owns timing, usage, funding, bank payment, responses and arrival effects. A purchased ordinary
* Karama price takes precedence over the native Guild half rate or its
* cancellation; an alliance alone does not grant either price. Independent
* Nexus and Junction prices belong to their own grants. */
@@ -74,8 +75,8 @@ export function quoteHomeworldShipment(
);
const native = context.players.find((p) => p.id === destination.native)!;
requireShipment(
native.id !== player.id || player.faction === 'guild',
'Shipment to your own Homeworld needs its specific return permission.',
native.id !== player.id || context.advanced || player.faction === 'guild',
'In Basic play, shipment to your own Homeworld needs its specific return permission.',
);
requireShipment(
!(player.ally === native.id && native.ally === player.id),
+2 -1
View File
@@ -147,7 +147,7 @@ const phaseDetails = [
'Native Guild cross/return permission has a separate unpaid response before native price. Preventing it preserves legal ordinary shipment or movement and does not remove half price. The conservative provisional denied scope is that original shipment opportunity; signed Cunning second opportunity is distinct. Native rate cancellation keeps the same paid units and approved funding, or releases an unaffordable attempt for a full-price replacement. Free Smuggler counters stay free; own/allied No-Field bills one marker. Immune Junction and independent card prices remain separate sources.',
'For movement, select the source forces. Enable Combine sectors to include several groups from the same territory.',
'A Fremen move using the two-territory advantage has a Karama response. Cancellation leaves the forces in place and limits this move to one territory; city ornithopters and a later extra move keep their normal rules.',
'Guild transport moves one exact physical group across the planet or returns it to reserves. Permission and price are separate counter opportunities; common world-to-foreign-world shipment does not require Guild cross/return privilege. Purchased half price grants no new route. Ordinary movement still checks range, storm and stronghold occupancy.',
'Guild transport moves one exact physical group across the planet or returns it to reserves. Permission and price are separate counter opportunities; Common World-to-World shipment does not require Guild cross/return privilege, including a return to the native World in Advanced. Purchased half price grants no new route. Ordinary movement still checks range, storm and stronghold occupancy.',
'You may pass through an ally’s territory on a legal route that ends elsewhere. Ordinary physical reserve shipments in both modes may enter allied territory before movement, then depart during that turn. Storm and stronghold capacity remain binding. Basic visibly labels its provisional no-exit policy: excess new visitors still present go to Tanks. Advanced follows supplied p15: all the ending player’s shared forces go to Tanks, including old forces, subject to advisor/Polar/Ecaz exemptions. Neither grants an extra move. Concealed No-Fields and optional arrivals remain separate.',
'Ecaz and its reciprocal ally may share territories and count as one faction toward stronghold capacity, without extra movement or storm/Homeworld exceptions. Their three-joint-stronghold victory and desert allocation are connected. Fremen/Ecaz cooccupation permits the Fremen special win in both Sietch Tabr and Habbanya Sietch; the Basic Habbanya allowance is a provisional interpretation. Other victory conditions and exceptional combined interactions remain separate.',
'A restored pending physical shipment is checked again before forces or spice are committed. If its saved turn, force allocation, destination, price or authorized contribution no longer matches the table, it is rejected without changing the saved declaration.',
@@ -5508,6 +5508,7 @@ export const RULE_TOPICS: RuleTopic[] = [
).join(' '),
steps: [
'Homeworlds are an optional module from Ecaz & Moritani, available under the official rules with Basic or Advanced play. They are separate locations outside Arrakis; they do not receive ordinary storm movement or count as ordinary strongholds.',
'Advanced permits a paid physical shipment from a different Homeworld back to your own, including either Emperor World. Guild may use this common route even if native cross/return transport is canceled; the Guild rate is separate. Basic keeps its existing Guild exception and own-World restriction. Arrakis and concealed No-Field return remain separate.',
'Clean World starts admit registered classic/no-deck and selected-family paired/mixed/all-three rosters with optional independent cards, Tech3–6 and Advanced Strongholds2–6. Skills or Nexus are not incidental prerequisites. Fresh setup includes original occupation qualification, bank/percentage benefits, native Tupile and Ecaz victory state alongside physical locations; existing played games are not retrofitted. Original module-specific profiles and complete-mode gates stay separate.',
'Fresh World all14 uses actual registered seats and selected ordinary decks in Basic/Advanced, including mixed Ecaz/Moritani with E1/E2 natives. Neither Nexus, independent cards, one exact family nor a seated native from every selected deck is required. Original Tech3+/Advanced Strongholds2+ may remain. Existing no-card Nexus/Discovery and Semuta keep their separate limits. Actual hands, Ix card-before-training and native five-disc assignment remain; Auditor/shared Duke never train. Native Suk saves stay at that home; external Emperor returns retain original typed destinations. Nested locations gain no ordinary Stronghold effect or invented saved history.',
'Fresh clean registered World/all14 starts also include original occupation benefit state beside normal Banker. Admission and native role limits remain. Real other-payer Bank payments can earn a deferred skill grant; occupied Collection and phase tokens do not become immediate Banker cash. Actual Mentat settles the original skill receipt once. Nexus/Discovery/Semuta contexts retain their own scope; played games are not retrofitted.',