Prototype native Homeworld No-Field return
Verify and publish checkpoint container / container (push) Canceled after 0s
Verify and publish checkpoint container / container (push) Canceled after 0s
This commit is contained in:
1 parent
89569e92a1
commit
7e3d745807
17 files changed
+540
-32
No files matched your search
+5
-2
@@ -4820,7 +4820,7 @@ function revealPlayerNoField(g: Game, p: Player, cause: NoFieldRevealCause) {
|
||||
p.noFieldEvent = crypto.randomUUID();
|
||||
if (isHomeworldNoFieldLocation(result.location)) {
|
||||
const destination = result.location.homeworld;
|
||||
if (result.forces) {
|
||||
if (result.forces && destination !== 'homeworld:richese') {
|
||||
const transfer = homeworldRule(() => quoteHomeworldCustody(homeworldContext(g), g.homeworlds!.custody!, [
|
||||
{ homeworld: 'homeworld:richese', player: p.id, withdraw: { normal: result.forces, elite: 0 }, deposit: { normal: 0, elite: 0 } },
|
||||
{ homeworld: destination, player: p.id, withdraw: { normal: 0, elite: 0 }, deposit: { normal: result.forces, elite: 0 } },
|
||||
@@ -4839,7 +4839,7 @@ function revealPlayerNoField(g: Game, p: Player, cause: NoFieldRevealCause) {
|
||||
observeOccupation(g);
|
||||
log(
|
||||
g,
|
||||
`${p.name} revealed the ${result.value} No-Field in ${isHomeworldNoFieldLocation(result.location) ? combatLocationName(g, result.location.homeworld) : territory(result.location.territory).name} (${cause === 'alliedSeparation' ? 'allied separation' : cause === 'discoveryBlow' ? 'Discovery spice blow; provisional destructive reveal' : cause}) and placed ${result.forces} physical forces from reserves.${result.forces < result.value ? ' Only the remaining reserves could be placed.' : ''}`,
|
||||
`${p.name} revealed the ${result.value} No-Field in ${isHomeworldNoFieldLocation(result.location) ? combatLocationName(g, result.location.homeworld) : territory(result.location.territory).name} (${cause === 'alliedSeparation' ? 'allied separation' : cause === 'discoveryBlow' ? 'Discovery spice blow; provisional destructive reveal' : cause})${isHomeworldNoFieldLocation(result.location) && result.location.homeworld === 'homeworld:richese' ? `; ${result.forces} represented forces are already in the native reserve pool.` : ` and placed ${result.forces} physical forces from reserves.`}${result.forces < result.value ? ' Only the remaining reserves could be placed.' : ''}`,
|
||||
{ faction: 'richese', name: 'No-Field revealed' },
|
||||
);
|
||||
return result;
|
||||
@@ -10719,6 +10719,9 @@ function killTerritory(
|
||||
* before requesting a pool. Actual reveal remains the native component action. */
|
||||
function prospectiveNoFieldForces(p: Player, territory: string): number {
|
||||
const marker = p.noField?.deployed;
|
||||
// On Richese's own World these physical reserves already constitute its
|
||||
// native army; revealing the marker does not create another copy of them.
|
||||
if (territory === 'homeworld:richese' && marker && noFieldAtCombatLocation(p, territory)) return 0;
|
||||
return marker && noFieldAtCombatLocation(p,territory)
|
||||
? Math.min(p.reserves, p.noField!.tokens.find(token => token.id === marker.tokenId)!.value)
|
||||
: 0;
|
||||
|
||||
@@ -16,8 +16,9 @@ export function homeworldAllianceBlock(
|
||||
if (marker) {
|
||||
const world = worlds.find(row => row.id === marker.homeworld);
|
||||
const controller = context.players.find(row => row.id === marker.controller);
|
||||
if (!world || !controller || controller.faction !== 'richese' || world.native === controller.id)
|
||||
throw new HomeworldCustodyError('Homeworld alliance marker needs its seated Richese controller and an active foreign world.');
|
||||
if (!world || !controller || controller.faction !== 'richese' ||
|
||||
world.native === controller.id && !context.advanced)
|
||||
throw new HomeworldCustodyError('Homeworld alliance marker needs its seated Richese controller and an active foreign world, or its own Homeworld in Advanced.');
|
||||
if ((world.native === first && controller.id === second) ||
|
||||
(world.native === second && controller.id === first))
|
||||
return 'An alliance cannot form while either faction has forces on the other’s Homeworld.';
|
||||
|
||||
@@ -98,8 +98,9 @@ function validateMarker(context: HomeworldCustodyContext, marker: HomeworldOccup
|
||||
'a public No-Field marker needs its original world and controller.');
|
||||
const home = homeworldLocations(context).find(row => row.id === marker.homeworld);
|
||||
const player = context.players.find(row => row.id === marker.controller);
|
||||
requireHistory(home && player && player.faction === 'richese' && home.native !== player.id,
|
||||
'a No-Field marker needs a seated Richese controller and an active foreign world.');
|
||||
requireHistory(home && player && player.faction === 'richese' &&
|
||||
(context.advanced || home.native !== player.id),
|
||||
'a No-Field marker needs a seated Richese controller and an active foreign world, or its own Homeworld in Advanced.');
|
||||
}
|
||||
|
||||
/** Extract only the public off-planet marker location. No token ID or hidden
|
||||
|
||||
+4
-3
@@ -1127,7 +1127,7 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
'In Basic play, your own single concealed No-Field may provisionally ship into an ally’s territory if it can legally enter; move it and any paid accompanying forces out before your turn ends. Paid companions require the High Richese Homeworld power. If the marker remains, reveal it and send its newly materialized forces to Tanks under the provisional no-departure policy. A zero marker reveals but contributes no casualties. Existing physical forces and the ally are not part of that new-visitor loss. Paired markers keep their separate guards.',
|
||||
'A normal No-Field shipment pays the one-force price. The concealed token moves like a force. Before Battle, Richese may reveal it voluntarily; a token involved in battle is revealed with the Battle Plan. Revelation brings the indicated forces from reserves, limited by what remains there.',
|
||||
'Provisional Guild transport treats your owned concealed marker as one billable force alongside any same-origin physical counters. Native Guild allies may cross-ship it through the normal permission and rate responses. The actual absent-Guild Secret Ally may cross-ship or return it face down, spending its Nexus once and paying the Bank. Cross keeps concealment; return creates no denomination-sized reserve deposit and retains the same-token next-shipment ban. Ordinary Guild allies cannot return. Select the marker separately from physical counters; ordinary movement remains available.',
|
||||
'In supported native Homeworld games, you may provisionally ship one concealed No-Field from your reserves to a foreign non-allied Homeworld, alone or with physical forces from those reserves. On a later turn, you may ship that same concealed marker between distinct eligible foreign Homeworlds, alone or with selected physical Richese counters from the marker’s current World. Price the whole group as one plus those counters; a purchased Guild rate halves the total, rounding up once. The marker retains its identity and last-shipment history, and its value does not materialize until reveal, when available reserves are placed there. Only one marker may be deployed globally. Own-Homeworld placement or return and optional-module combinations remain unavailable. The supplied revised rulebook permits World-to-World shipment (physical p. 22) and counts a concealed marker as one force for effects (physical p. 36), but does not explicitly resolve this combination; this is a provisional interpretation.',
|
||||
'In supported native Homeworld games, you may provisionally ship one concealed No-Field from your reserves to a foreign non-allied Homeworld, alone or with physical forces from those reserves. On a later turn, you may ship that same concealed marker between distinct eligible Homeworlds, alone or with selected physical Richese counters from the marker’s current World; its own Homeworld is an eligible endpoint only in Advanced. Price the whole group as one plus those counters; a purchased Guild rate halves the total, rounding up once. The marker retains its identity and last-shipment history, and its value does not materialize until reveal; available reserves are placed there unless it is already on its own World, where the physical pool stays unchanged. Only one marker may be deployed globally. Fresh placement from the screen to your own Homeworld and optional-module combinations remain unavailable; an Advanced native return uses the provisional physical-reserve interpretation described below. The supplied revised rulebook permits World-to-World shipment (physical p. 22) and counts a concealed marker as one force for effects (physical p. 36), but does not explicitly resolve this combination; this is a provisional interpretation.',
|
||||
'With a living, uncaptured Planetologist, your own concealed marker may provisionally use either ordinary movement alternative. Extra range adds one, capped at three, for one origin. Gathering combines exactly two territories at one destination using each selected sector’s ordinary range; the marker can supply one origin alone or with physical companions, and physical counters supply the other. The alternatives do not stack. The marker stays concealed, including zero, and spends one movement without materializing reserves. Physical and Discovery flight use the provisional skill transport policy with original marker quotas; complete combinations remain unfinished.',
|
||||
'The revealed token stays face up until another token is placed. Revealing it does not clear the previous-shipment restriction. An allied No-Field shipment reveals immediately and uses the ally’s reserves; an existing token must be revealed before another shipment.',
|
||||
'Before an eligible ally uses its shipment, the game holds an offer opportunity for Richese. Richese may pass or privately propose a token, destination and payment. The ally accepts the exact offer and chooses its permitted regular/elite mix, or declines without payment. Success consumes the ally’s shipment, not Richese’s shipment or either player’s movement.',
|
||||
@@ -1330,7 +1330,7 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
: definition.card.effect === 'ornithopter'
|
||||
? 'Use the Ornithopter controls with one unused normal/Hajr movement and a selected group/destination. Two card groups stay distinct, while Hajr may reuse their forces afterward. A genuinely recovered Hajr may be legally replayed for another grant. Advanced needs a fresh immediate-after-movement opportunity. Kulon retains the fixed maximum three and extends both normal groups. Advisor/card and wider module combinations remain unfinished.'
|
||||
: definition.card.effect === 'residualPoison'
|
||||
? 'Use the Residual Poison panel before either combatant commits a leader. A shared preparation step provides an opportunity regardless of hand contents; advanced Harkonnen tables remain guarded pending the secret-captive ruling. In the explicit Semuta preview, including the supported Basic independent-card profile, a clean death pauses after public disposal for the neutral offer even if one combatant is already ready. The opponent’s readiness remains; the Poison player must ready again. Inspected battle commitments remain outside this reaction.'
|
||||
? 'Use the Residual Poison panel before either combatant commits a leader. A shared preparation step provides an opportunity regardless of hand contents. Advanced Harkonnen captives are included under the provisional public selected-death interpretation; unselected captives remain concealed. In the explicit Semuta preview, including the supported Basic independent-card profile, a clean death pauses after public disposal for the neutral offer even if one combatant is already ready. The opponent’s readiness remains; the Poison player must ready again. Inspected battle commitments remain outside this reaction.'
|
||||
: definition.card.effect === 'stoneBurner'
|
||||
? 'Use Stone Burner in the weapon selector and review public dial/support feasibility before sealing. Clean selected CHOAM/Ix now uses visibly provisional original Stone-first then uncopied Tooth order; copy-first and physical allocation guards remain.'
|
||||
: definition.card.effect === 'mirrorWeapon'
|
||||
@@ -5508,7 +5508,8 @@ 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.',
|
||||
'In the provisional Advanced native Richese preview, a deployed No-Field may ship from another Homeworld to its own and later leave. It stays concealed as public presence; native reserves remain one physical pool and are not duplicated when it reveals. Population and other interactions remain provisional; Basic retains the foreign-World restriction.',
|
||||
'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 return and other concealed No-Field interactions 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.',
|
||||
|
||||
@@ -35,8 +35,8 @@ export function homeworldNoFieldPresence(
|
||||
if (!owner || owner.faction !== 'richese')
|
||||
throw new Error('A Homeworld No-Field needs its seated Richese controller.');
|
||||
const home = homeworldCombatLocation(context, custody, marker.location.homeworld);
|
||||
if (home.native === owner.id)
|
||||
throw new Error('A concealed No-Field on its own Homeworld is not supported.');
|
||||
if (home.native === owner.id && !context.advanced)
|
||||
throw new Error('A concealed No-Field on its own Homeworld is not supported in Basic.');
|
||||
return { homeworld: home.id, controller: owner.id, effectiveForces: 1 };
|
||||
}
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ export function quoteRicheseHomeworldMarkerShipment(
|
||||
|
||||
/** A deployed marker can be transported like one force between eligible
|
||||
* Homeworlds, provisionally alongside physical forces from that same source.
|
||||
* Advanced permits a native Homeworld endpoint; Basic remains foreign-only.
|
||||
* Its denomination never enters the price or physical custody. */
|
||||
export function quoteRicheseHomeworldMarkerTransfer(
|
||||
context: HomeworldShipmentContext,
|
||||
@@ -119,9 +120,9 @@ export function quoteRicheseHomeworldMarkerTransfer(
|
||||
const player = context.players.find(seat => seat.id === intent.player);
|
||||
const source = worlds.find(world => world.id === intent.source);
|
||||
const destination = worlds.find(world => world.id === intent.destination);
|
||||
requireMarker(player?.faction === 'richese' && source && destination &&
|
||||
source.native !== player.id && destination.native !== player.id && source.id !== destination.id,
|
||||
'Choose two different active foreign Homeworlds for native Richese.');
|
||||
requireMarker(player?.faction === 'richese' && source && destination && source.id !== destination.id &&
|
||||
(context.advanced || (source.native !== player.id && destination.native !== player.id)),
|
||||
'Choose two different active Homeworlds; Basic marker transfers require foreign Homeworlds.');
|
||||
const native = context.players.find(seat => seat.id === destination.native)!;
|
||||
requireMarker(!(player.ally === native.id && native.ally === player.id),
|
||||
'You cannot ship to your ally’s Homeworld.');
|
||||
|
||||
Reference in new issue
Block a user