types.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. export const RARITIES = [
  2. 'common',
  3. 'uncommon',
  4. 'rare',
  5. 'epic',
  6. 'legendary',
  7. ] as const
  8. export type Rarity = (typeof RARITIES)[number]
  9. // One species name collides with a model-codename canary in excluded-strings.txt.
  10. // The check greps build output (not source), so runtime-constructing the value keeps
  11. // the literal out of the bundle while the check stays armed for the actual codename.
  12. // All species encoded uniformly; `as` casts are type-position only (erased pre-bundle).
  13. const c = String.fromCharCode
  14. // biome-ignore format: keep the species list compact
  15. export const duck = c(0x64,0x75,0x63,0x6b) as 'duck'
  16. export const goose = c(0x67, 0x6f, 0x6f, 0x73, 0x65) as 'goose'
  17. export const blob = c(0x62, 0x6c, 0x6f, 0x62) as 'blob'
  18. export const cat = c(0x63, 0x61, 0x74) as 'cat'
  19. export const dragon = c(0x64, 0x72, 0x61, 0x67, 0x6f, 0x6e) as 'dragon'
  20. export const octopus = c(0x6f, 0x63, 0x74, 0x6f, 0x70, 0x75, 0x73) as 'octopus'
  21. export const owl = c(0x6f, 0x77, 0x6c) as 'owl'
  22. export const penguin = c(0x70, 0x65, 0x6e, 0x67, 0x75, 0x69, 0x6e) as 'penguin'
  23. export const turtle = c(0x74, 0x75, 0x72, 0x74, 0x6c, 0x65) as 'turtle'
  24. export const snail = c(0x73, 0x6e, 0x61, 0x69, 0x6c) as 'snail'
  25. export const ghost = c(0x67, 0x68, 0x6f, 0x73, 0x74) as 'ghost'
  26. export const axolotl = c(0x61, 0x78, 0x6f, 0x6c, 0x6f, 0x74, 0x6c) as 'axolotl'
  27. export const capybara = c(
  28. 0x63,
  29. 0x61,
  30. 0x70,
  31. 0x79,
  32. 0x62,
  33. 0x61,
  34. 0x72,
  35. 0x61,
  36. ) as 'capybara'
  37. export const cactus = c(0x63, 0x61, 0x63, 0x74, 0x75, 0x73) as 'cactus'
  38. export const robot = c(0x72, 0x6f, 0x62, 0x6f, 0x74) as 'robot'
  39. export const rabbit = c(0x72, 0x61, 0x62, 0x62, 0x69, 0x74) as 'rabbit'
  40. export const mushroom = c(
  41. 0x6d,
  42. 0x75,
  43. 0x73,
  44. 0x68,
  45. 0x72,
  46. 0x6f,
  47. 0x6f,
  48. 0x6d,
  49. ) as 'mushroom'
  50. export const chonk = c(0x63, 0x68, 0x6f, 0x6e, 0x6b) as 'chonk'
  51. export const SPECIES = [
  52. duck,
  53. goose,
  54. blob,
  55. cat,
  56. dragon,
  57. octopus,
  58. owl,
  59. penguin,
  60. turtle,
  61. snail,
  62. ghost,
  63. axolotl,
  64. capybara,
  65. cactus,
  66. robot,
  67. rabbit,
  68. mushroom,
  69. chonk,
  70. ] as const
  71. export type Species = (typeof SPECIES)[number] // biome-ignore format: keep compact
  72. export const EYES = ['·', '✦', '×', '◉', '@', '°'] as const
  73. export type Eye = (typeof EYES)[number]
  74. export const HATS = [
  75. 'none',
  76. 'crown',
  77. 'tophat',
  78. 'propeller',
  79. 'halo',
  80. 'wizard',
  81. 'beanie',
  82. 'tinyduck',
  83. ] as const
  84. export type Hat = (typeof HATS)[number]
  85. export const STAT_NAMES = [
  86. 'DEBUGGING',
  87. 'PATIENCE',
  88. 'CHAOS',
  89. 'WISDOM',
  90. 'SNARK',
  91. ] as const
  92. export type StatName = (typeof STAT_NAMES)[number]
  93. // Deterministic parts — derived from hash(userId)
  94. export type CompanionBones = {
  95. rarity: Rarity
  96. species: Species
  97. eye: Eye
  98. hat: Hat
  99. shiny: boolean
  100. stats: Record<StatName, number>
  101. }
  102. // Model-generated soul — stored in config after first hatch
  103. export type CompanionSoul = {
  104. name: string
  105. personality: string
  106. }
  107. export type Companion = CompanionBones &
  108. CompanionSoul & {
  109. hatchedAt: number
  110. }
  111. // What actually persists in config. Bones are regenerated from hash(userId)
  112. // on every read so species renames don't break stored companions and users
  113. // can't edit their way to a legendary.
  114. export type StoredCompanion = CompanionSoul & { hatchedAt: number }
  115. export const RARITY_WEIGHTS = {
  116. common: 60,
  117. uncommon: 25,
  118. rare: 10,
  119. epic: 4,
  120. legendary: 1,
  121. } as const satisfies Record<Rarity, number>
  122. export const RARITY_STARS = {
  123. common: '★',
  124. uncommon: '★★',
  125. rare: '★★★',
  126. epic: '★★★★',
  127. legendary: '★★★★★',
  128. } as const satisfies Record<Rarity, string>
  129. export const RARITY_COLORS = {
  130. common: 'inactive',
  131. uncommon: 'success',
  132. rare: 'permission',
  133. epic: 'autoAccept',
  134. legendary: 'warning',
  135. } as const satisfies Record<Rarity, keyof import('../utils/theme.js').Theme>