ninelands-reddit/src/client/texts.ts
Lukas Müllner 51d47cd0d0 feat: Realm-Auswahl (Farbe, Volk, Thema, Banner), Freischaltungen, Flair, Ergebnis als Kommentar
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 17:33:53 +01:00

122 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Englische Texte (aus dem Hauptspiel übernommen und für die Reddit-Fassung gekürzt).
import type {PlacementError} from '../engine/core/Game.ts'
import type {UnitType} from '../engine/core/units.ts'
import {
BASE_PIECE_COSTS,
getPieceCost,
type WorldTrait,
} from '../engine/core/WorldRules.ts'
export const UNIT_NAME: Record<UnitType, string> = {
HIVEMOTHER: 'Castle',
DRONE: 'Knight',
HIVEWORKER: 'Farmer',
HIVESCOUT: 'Bishop',
}
export const UNIT_DESC: Record<UnitType, string> = {
HIVEMOTHER: 'Up to 5 cells in straight lines · only once',
DRONE: '2 cells straight, stays in its land · 2× yield',
HIVEWORKER: 'The 8 surrounding cells in its own land',
HIVESCOUT: '2 cells diagonally, also across borders',
}
export const ZONE_NAMES = [
'Crownland',
'Northmarch',
'Oakgrove',
'Millvale',
'Ravenrock',
'Lakeland',
'Westwood',
'Stonequarry',
'Hillcountry',
]
export function lawName(trait: WorldTrait): string {
return (
(
{
TANDEM_MINING: 'Mining partnership',
SINGLE_WORKER_PER_ROOM: 'One farm per land',
DOUBLE_DRONE_COST: 'Costly knights',
DOUBLE_SCOUT_COST: 'Costly bishops',
CHEAP_DRONES: "In the king's pay",
NONE: 'No law',
} as Record<string, string>
)[trait] ?? 'No law'
)
}
export function lawText(trait: WorldTrait): string {
const knight = getPieceCost('DRONE', trait)
const bishop = getPieceCost('HIVESCOUT', trait)
switch (trait) {
case 'TANDEM_MINING':
return 'Ore and herbs are only mined once 2 of your pieces stand in the same land.'
case 'SINGLE_WORKER_PER_ROOM':
return 'Each land may hold at most one farmer.'
case 'DOUBLE_DRONE_COST':
return `Knights cost ${knight} gold instead of ${BASE_PIECE_COSTS.DRONE}.`
case 'DOUBLE_SCOUT_COST':
return `Bishops cost ${bishop} gold instead of ${BASE_PIECE_COSTS.HIVESCOUT}.`
case 'CHEAP_DRONES':
return `Knights cost only ${knight} gold instead of ${BASE_PIECE_COSTS.DRONE}.`
default:
return 'No special rule today.'
}
}
export function placementError(
unit: UnitType,
error: PlacementError,
cost: number,
gold: number,
): string {
switch (error) {
case 'NOT_AFFORDABLE':
return `Not enough gold: the ${UNIT_NAME[unit].toLowerCase()} costs ${cost}, you have ${gold}.`
case 'UNIT_LIMIT':
return 'You only have one castle.'
case 'OCCUPIED':
return 'There is already a piece here.'
case 'LAKE':
return 'Nothing can be built on a lake.'
case 'BIOME_FORBIDDEN':
return unit === 'HIVEMOTHER'
? 'A castle cannot stand in the moor.'
: 'A farmer cannot work in the moor.'
case 'ZONE_UNIT_LIMIT':
return 'Law of the realm: this land already has a farmer.'
case 'NO_MOTHER':
return 'Place your castle first – it founds your realm.'
case 'IN_ZOI':
return 'This land is already claimed – nothing may be built here.'
case 'DOCK_OTHER_ZONE':
return `The ${UNIT_NAME[unit].toLowerCase()} cannot connect here: the neighbouring domain lies in another land.`
case 'NOT_DOCKED':
if (unit === 'DRONE')
return "The knight's domain must touch your domain in the same land."
if (unit === 'HIVESCOUT')
return "The bishop's domain must touch your domain."
return 'The farmer must border your domain directly, in the same land.'
default:
return 'That does not fit here.'
}
}
/** Kurze Hinweise im Spiel statt einer Textwand (Jury: „contextual hints“) */
export const HINTS = {
castle:
'Tap a cell to place your castle. It claims land in straight lines – nothing can be built on claimed land later.',
farmer:
'Farmers are free: place one right next to your claimed land, in the same land. Pasture pays 5 gold per cell.',
general:
'Ore ⛰ and herbs 🌿 pay 20 gold. Knights pay double. Keep going until no move is left.',
touch: 'Tap again to place.',
noGain:
'None of your remaining moves earns gold – end the game to keep your gold.',
allStars: 'All 3 stars! Keep going for more gold – or end the game.',
} as const
export {starsLine} from '../shared/format.ts'