From 40e351d0edab558ad55df555eb7c5818175aa1a2 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Thu, 18 Jun 2026 01:38:19 +0900 Subject: [PATCH] Tighten card prompt camera and pose diversity constraints --- tools/export-card-assets.mjs | 40 ++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/tools/export-card-assets.mjs b/tools/export-card-assets.mjs index cf04890..d125e59 100644 --- a/tools/export-card-assets.mjs +++ b/tools/export-card-assets.mjs @@ -379,36 +379,36 @@ const CAMERA_VIEW_ANGLE_HINTS = { const CAMERA_STAGE_REQUIREMENTS = { normal: { - 0: ["side", "low"], + 0: ["low", "side", "high"], 1: ["high", "side", "rear"], 2: ["low", "high"], 3: ["rear", "low", "high"], - 4: ["side", "high", "rear"], + 4: ["high", "rear", "low"], }, "light-damage": { - 0: ["low", "high"], - 1: ["side", "rear"], + 0: ["low"], + 1: ["high", "side"], 2: ["low", "side", "high"], 3: ["rear", "low"], 4: ["high", "rear", "side"], }, "medium-damage": { - 0: ["side", "rear", "low"], + 0: ["low", "high", "side"], 1: ["low", "high"], 2: ["high", "side", "rear"], 3: ["rear", "low", "high"], - 4: ["side", "high", "low"], + 4: ["high", "side", "low"], }, "heavy-damage": { 0: ["low", "high"], 1: ["high", "low", "rear"], 2: ["rear", "low", "high"], - 3: ["rear", "low"], + 3: ["rear", "low", "high"], 4: ["high", "rear", "side"], }, defeated: { 0: ["rear", "low", "high"], - 1: ["low", "side"], + 1: ["low", "high", "side"], 2: ["high", "rear", "side"], 3: ["side", "rear", "low"], 4: ["side", "high", "low"], @@ -786,14 +786,16 @@ const POSE_VARIANTS = { const LOW_HIGH_CAMERA_PHRASES = { low: [ - "low-angle ground-lean with one knee absorbing impact and hips thrust backward", + "low-angle shot from knee height with one knee absorbing impact while hips thrust backward", "low-side dramatic weight shift with torn cloth and visible foot torque", - "ultra low perspective from knee height showing stagger and impact on armor seams", + "ultra low perspective from floor line where damaged armor is dragged toward the lens", + "ground-lean low-angle setup with body dropping through force and torso cut by the floor", ], high: [ - "high-angle top-down recoil shot while torso and hips remain readable", - "elevated overhead angle with character weight dropping toward ground and torn panels opening", + "high-angle top-down recoil shot with torso and hips clearly readable against the background", + "elevated overhead angle with character weight dropping toward ground and torn panels opening outward", "steep high-angle cut to show back-foot recovery, impact direction, and body distortion", + "high-angle shoulder-side perspective with shoulders bent from recoil and armor seams stretched toward frame", ], rear: [ "high-tension rear-side sweep showing opened back panel and collapsing shoulder", @@ -1048,6 +1050,12 @@ function promptFor(character, stage) { const requiredCamera = camera.orientation; const poseOptions = poseCandidates(spec, stage); const cameraOptions = orientationCandidates(spec, stage); + const elevationHintByOrientation = { + side: "side profile with clear 15 to 45 degree camera turn", + rear: "rear-three-quarter offset with shoulders not facing the lens", + low: "ground-level low-angle composition", + high: "high-angle composition from above the character", + }[camera.orientation] ?? "non-frontal camera angle"; const shotLock = cameraOptions.length > 1 ? `shot ${stage + 1}: one of [${cameraOptions.join(", ")}] camera families` @@ -1064,6 +1072,10 @@ function promptFor(character, stage) { "Do not output front-facing framing for any combat shot. If the first draft is front-facing, it is rejected and must be regenerated."; const angleHardStop = "Hard stop: frontal, direct eye-level, or symmetrical front-on compositions are disallowed for combat coverage."; + const antiRepeatPoseConstraint = + "Pose lock rule: the action family must change every shot; no two adjacent stages can share the same core action family."; + const cameraAntiRepeatConstraint = + "Camera lock rule: adjacent shots should not use the same angle family; rotate at least once between side/rear/low/high families."; const poseDiversityConstraint = "Pose diversity is mandatory: rotate through guard, movement, recoil, evasive, grounded, and collapse actions across the five stages; do not repeat the same motion family in multiple consecutive shots."; const poseHardStop = @@ -1095,7 +1107,7 @@ function promptFor(character, stage) { `Identity lock across stages: preserve the exact same person in every damage stage--same race/species, ear shape, face structure, eye shape, nose, lips, skin tone, hair color, hair length, hairstyle, body proportions, bust shape, and mature presence. Damage may change clothing, armor, pose, expression, dirt, sweat, and injury reaction, but must never change a human into an elf, change ear shape, change hair color, change age, change ethnicity, or replace the character with a different-looking person.`, `Personality and pose: ${character.personality}; ${character.pose}; ${spec.poseNote}; ${poseModifier}.`, `Facial expression: ${spec.expression}.`, - `Camera/view variation: ${camera.orientation} angle. ${poseAngleHint}. Composition directive: ${camera.phrase}.`, + `Camera/view variation: ${camera.orientation} angle. ${poseAngleHint}. ${elevationHintByOrientation}. Composition directive: ${camera.phrase}.`, requiredCameraLock, orientationPriority, `Shot constraint: ${poseLockHint}; ${poseFamilyHint}`, @@ -1103,8 +1115,10 @@ function promptFor(character, stage) { angleControl, angleConstraint, angleHardStop, + cameraAntiRepeatConstraint, poseDiversityConstraint, poseHardStop, + antiRepeatPoseConstraint, "Across the character's five damage stages, rotate between side, rear, low-angle, and high-angle views as the primary framing. Frontal composition is disallowed, and at least one low-angle and one high-angle shot must appear.", `Camera constraint: ${CAMERA_ORIENTATION_RULES[spec.label] ?? CAMERA_ORIENTATION_RULES.normal}`, `Adult visual appeal: ${character.appealFocus}; ${adultAppeal}.`,