feat: update evolution guide with new interaction rules and enhance styling for clarity

This commit is contained in:
sha
2026-02-21 23:33:26 +02:00
parent b6379a0bd3
commit 39e4b2d3cf
3 changed files with 57 additions and 30 deletions
+25 -16
View File
@@ -89,34 +89,43 @@
<p class="guide-section__label">interactions</p> <p class="guide-section__label">interactions</p>
<ul class="guide-rules"> <ul class="guide-rules">
<li class="guide-rule"> <li class="guide-rule">
<span class="guide-rule__dot" style="--c:#ffb0a8"></span> <span class="guide-entity__icon" data-guide-icon="bug"></span>
<span class="guide-rule__op">+</span> <span class="guide-rule__op">+</span>
<span class="guide-rule__dot" style="--c:#a8ffb8"></span> <span class="guide-entity__icon" data-guide-icon="dna-bold-duotone"></span>
<span class="guide-rule__desc">bug infects → <span style="color:#ff4d6d">virus</span></span> <span class="guide-rule__op"></span>
<span class="guide-entity__icon" data-guide-icon="virus-filled"></span>
<span class="guide-rule__desc">bug infects</span>
</li> </li>
<li class="guide-rule"> <li class="guide-rule">
<span class="guide-rule__dot" style="--c:#ffb0a8"></span> <span class="guide-entity__icon" data-guide-icon="bug"></span>
<span class="guide-rule__op">+</span> <span class="guide-rule__op">+</span>
<span class="guide-rule__dot" style="--c:#ff4d6d"></span> <span class="guide-entity__icon" data-guide-icon="virus-filled"></span>
<span class="guide-rule__desc">bug cures → <span style="color:#a8ffb8">dna</span></span> <span class="guide-rule__op"></span>
<span class="guide-entity__icon" data-guide-icon="dna-bold-duotone"></span>
<span class="guide-rule__desc">bug cures virus</span>
</li> </li>
<li class="guide-rule"> <li class="guide-rule">
<span class="guide-rule__dot" style="--c:#ff4d6d"></span> <span class="guide-entity__icon" data-guide-icon="virus-filled"></span>
<span class="guide-rule__op">+</span> <span class="guide-rule__op">+</span>
<span class="guide-rule__dot" style="--c:#a8ffb8"></span> <span class="guide-entity__icon" data-guide-icon="dna-bold-duotone"></span>
<span class="guide-rule__desc">virus kills &nbsp;<span class="guide-rule__pct">90%</span></span> <span class="guide-rule__op"></span>
<span class="guide-rule__pct">90%</span>
<span class="guide-rule__desc">virus kills</span>
</li> </li>
<li class="guide-rule"> <li class="guide-rule">
<span class="guide-rule__dot" style="--c:#ff4d6d"></span> <span class="guide-entity__icon" data-guide-icon="virus-filled"></span>
<span class="guide-rule__op">+</span> <span class="guide-rule__op">+</span>
<span class="guide-rule__dot" style="--c:#a8ffb8"></span> <span class="guide-entity__icon" data-guide-icon="dna-bold-duotone"></span>
<span class="guide-rule__desc">mutates → <span style="color:#80ffee">bacteria</span> <span class="guide-rule__pct">10%</span></span> <span class="guide-rule__op"></span>
<span class="guide-entity__icon" data-guide-icon="bacteria"></span>
<span class="guide-rule__pct">10%</span>
<span class="guide-rule__desc">mutation</span>
</li> </li>
<li class="guide-rule"> <li class="guide-rule">
<span class="guide-rule__dot" style="--c:#80ffee"></span> <span class="guide-entity__icon" data-guide-icon="bacteria"></span>
<span class="guide-rule__op"></span> <span class="guide-rule__op">×</span>
<span class="guide-rule__dot" style="--c:transparent;box-shadow:none;border:1px solid rgba(255,255,255,0.18)"></span> <span class="guide-entity__icon" data-guide-icon="virus-filled"></span>
<span class="guide-rule__desc">bacteria immune to virus</span> <span class="guide-rule__desc">bacteria immune</span>
</li> </li>
</ul> </ul>
</div> </div>
+15 -5
View File
@@ -385,7 +385,10 @@ export class EvolutionController {
} }
// ── Virus kill / mutation ────────────────────────────── // ── Virus kill / mutation ──────────────────────────────
// virus-filled hitting a non-immune entity: 90% kills it, 10% triggers mutation. // virus-filled hitting a non-immune entity: the target may die or mutate.
// On a failed kill roll the contact will convert the target into bacteria
// (10% shown in the guide) if that icon exists. Bacteria are immune to
// subsequent virus or bug interactions.
const virusImmune = new Set(['bug', 'virus-filled', 'bacteria']); const virusImmune = new Set(['bug', 'virus-filled', 'bacteria']);
const aIsVirus = a.entityKey === 'virus-filled'; const aIsVirus = a.entityKey === 'virus-filled';
const bIsVirus = b.entityKey === 'virus-filled'; const bIsVirus = b.entityKey === 'virus-filled';
@@ -403,10 +406,11 @@ export class EvolutionController {
/** /**
* Handle a collision between a virus-filled entity and a vulnerable target. * Handle a collision between a virus-filled entity and a vulnerable target.
* Bug is the sole mutation/transformation trigger — virus only kills.
* *
* - virusKillChance: target begins slow-death sequence. * 50%100% of the time (controlled by virusKillChance) the target is killed.
* - else: target survives unaffected (virus bounces away normally). * On the remaining rolls the virus fails to kill and the contact triggers a
* rare mutation: the target becomes a "bacteria" entity if that icon is
* defined. Bacteria are immune to further virus attacks and bugs.
* *
* @param {import('./entity.js').Entity} _virus the virus-filled entity (unused) * @param {import('./entity.js').Entity} _virus the virus-filled entity (unused)
* @param {import('./entity.js').Entity} target the entity being contacted * @param {import('./entity.js').Entity} target the entity being contacted
@@ -414,8 +418,14 @@ export class EvolutionController {
#resolveVirusContact(_virus, target) { #resolveVirusContact(_virus, target) {
if (Math.random() < this.#virusKillChance) { if (Math.random() < this.#virusKillChance) {
target.die(); target.die();
} else {
// mutation path only if bacteria is registered
if (this.#iconsData && this.#iconsData.icons['bacteria']) {
const bacMeta = this.#iconsData.icons['bacteria'];
const bacColor = this.#iconsData.types[bacMeta.type]?.color || '#80ffee';
target.infectWith('bacteria', bacColor, { force: true });
}
} }
// else: target survives — virus bounces, no transformation
} }
// ── State persistence ──────────────────────────────────────── // ── State persistence ────────────────────────────────────────
+17 -9
View File
@@ -106,10 +106,10 @@
/* Icon container — SVG injected here by guide.js */ /* Icon container — SVG injected here by guide.js */
.guide-entity__icon { .guide-entity__icon {
width: 16px; width: 18px;
height: 16px; height: 18px;
flex-shrink: 0; flex-shrink: 0;
color: var(--c, rgba(255, 255, 255, 0.6)); color: var(--c, rgba(255, 255, 255, 0.75));
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -154,10 +154,11 @@
} }
.guide-rule { .guide-rule {
display: grid; display: flex;
grid-template-columns: 9px 9px 9px 1fr;
align-items: center; align-items: center;
gap: 0.28rem; gap: 0.4rem;
flex-wrap: nowrap; /* absolutely no wrapping */
white-space: nowrap; /* safeguard for inline elements */
} }
/* Coloured circle representing an entity type */ /* Coloured circle representing an entity type */
@@ -172,9 +173,14 @@
.guide-rule__op { .guide-rule__op {
font-family: var(--font-mono); font-family: var(--font-mono);
font-size: 0.55rem; display: inline-block;
color: rgba(255, 255, 255, 0.22); /* 1.2rem ≈ 19px on a 16px root, sized to match the 18px icons */
font-size: 1.2rem;
line-height: 1;
font-weight: 500;
color: rgba(255, 255, 255, 0.75);
text-align: center; text-align: center;
flex-shrink: 0;
} }
.guide-rule__desc { .guide-rule__desc {
@@ -182,11 +188,13 @@
font-size: 0.62rem; font-size: 0.62rem;
color: rgba(255, 255, 255, 0.45); color: rgba(255, 255, 255, 0.45);
line-height: 1.3; line-height: 1.3;
margin-left: 0.4rem;
} }
.guide-rule__pct { .guide-rule__pct {
color: rgba(255, 255, 255, 0.22); color: rgba(255, 255, 255, 0.22);
font-size: 0.58rem; font-size: 0.7rem;
flex-shrink: 0;
} }
/* ── Guide footer + restart button ───────────────────────── */ /* ── Guide footer + restart button ───────────────────────── */