source dump of claude code
at main 514 lines 9.8 kB view raw
1import type { CompanionBones, Eye, Hat, Species } from './types.js' 2import { 3 axolotl, 4 blob, 5 cactus, 6 capybara, 7 cat, 8 chonk, 9 dragon, 10 duck, 11 ghost, 12 goose, 13 mushroom, 14 octopus, 15 owl, 16 penguin, 17 rabbit, 18 robot, 19 snail, 20 turtle, 21} from './types.js' 22 23// Each sprite is 5 lines tall, 12 wide (after {E}→1char substitution). 24// Multiple frames per species for idle fidget animation. 25// Line 0 is the hat slot — must be blank in frames 0-1; frame 2 may use it. 26const BODIES: Record<Species, string[][]> = { 27 [duck]: [ 28 [ 29 ' ', 30 ' __ ', 31 ' <({E} )___ ', 32 ' ( ._> ', 33 ' `--´ ', 34 ], 35 [ 36 ' ', 37 ' __ ', 38 ' <({E} )___ ', 39 ' ( ._> ', 40 ' `--´~ ', 41 ], 42 [ 43 ' ', 44 ' __ ', 45 ' <({E} )___ ', 46 ' ( .__> ', 47 ' `--´ ', 48 ], 49 ], 50 [goose]: [ 51 [ 52 ' ', 53 ' ({E}> ', 54 ' || ', 55 ' _(__)_ ', 56 ' ^^^^ ', 57 ], 58 [ 59 ' ', 60 ' ({E}> ', 61 ' || ', 62 ' _(__)_ ', 63 ' ^^^^ ', 64 ], 65 [ 66 ' ', 67 ' ({E}>> ', 68 ' || ', 69 ' _(__)_ ', 70 ' ^^^^ ', 71 ], 72 ], 73 [blob]: [ 74 [ 75 ' ', 76 ' .----. ', 77 ' ( {E} {E} ) ', 78 ' ( ) ', 79 ' `----´ ', 80 ], 81 [ 82 ' ', 83 ' .------. ', 84 ' ( {E} {E} ) ', 85 ' ( ) ', 86 ' `------´ ', 87 ], 88 [ 89 ' ', 90 ' .--. ', 91 ' ({E} {E}) ', 92 ' ( ) ', 93 ' `--´ ', 94 ], 95 ], 96 [cat]: [ 97 [ 98 ' ', 99 ' /\\_/\\ ', 100 ' ( {E} {E}) ', 101 ' ( ω ) ', 102 ' (")_(") ', 103 ], 104 [ 105 ' ', 106 ' /\\_/\\ ', 107 ' ( {E} {E}) ', 108 ' ( ω ) ', 109 ' (")_(")~ ', 110 ], 111 [ 112 ' ', 113 ' /\\-/\\ ', 114 ' ( {E} {E}) ', 115 ' ( ω ) ', 116 ' (")_(") ', 117 ], 118 ], 119 [dragon]: [ 120 [ 121 ' ', 122 ' /^\\ /^\\ ', 123 ' < {E} {E} > ', 124 ' ( ~~ ) ', 125 ' `-vvvv-´ ', 126 ], 127 [ 128 ' ', 129 ' /^\\ /^\\ ', 130 ' < {E} {E} > ', 131 ' ( ) ', 132 ' `-vvvv-´ ', 133 ], 134 [ 135 ' ~ ~ ', 136 ' /^\\ /^\\ ', 137 ' < {E} {E} > ', 138 ' ( ~~ ) ', 139 ' `-vvvv-´ ', 140 ], 141 ], 142 [octopus]: [ 143 [ 144 ' ', 145 ' .----. ', 146 ' ( {E} {E} ) ', 147 ' (______) ', 148 ' /\\/\\/\\/\\ ', 149 ], 150 [ 151 ' ', 152 ' .----. ', 153 ' ( {E} {E} ) ', 154 ' (______) ', 155 ' \\/\\/\\/\\/ ', 156 ], 157 [ 158 ' o ', 159 ' .----. ', 160 ' ( {E} {E} ) ', 161 ' (______) ', 162 ' /\\/\\/\\/\\ ', 163 ], 164 ], 165 [owl]: [ 166 [ 167 ' ', 168 ' /\\ /\\ ', 169 ' (({E})({E})) ', 170 ' ( >< ) ', 171 ' `----´ ', 172 ], 173 [ 174 ' ', 175 ' /\\ /\\ ', 176 ' (({E})({E})) ', 177 ' ( >< ) ', 178 ' .----. ', 179 ], 180 [ 181 ' ', 182 ' /\\ /\\ ', 183 ' (({E})(-)) ', 184 ' ( >< ) ', 185 ' `----´ ', 186 ], 187 ], 188 [penguin]: [ 189 [ 190 ' ', 191 ' .---. ', 192 ' ({E}>{E}) ', 193 ' /( )\\ ', 194 ' `---´ ', 195 ], 196 [ 197 ' ', 198 ' .---. ', 199 ' ({E}>{E}) ', 200 ' |( )| ', 201 ' `---´ ', 202 ], 203 [ 204 ' .---. ', 205 ' ({E}>{E}) ', 206 ' /( )\\ ', 207 ' `---´ ', 208 ' ~ ~ ', 209 ], 210 ], 211 [turtle]: [ 212 [ 213 ' ', 214 ' _,--._ ', 215 ' ( {E} {E} ) ', 216 ' /[______]\\ ', 217 ' `` `` ', 218 ], 219 [ 220 ' ', 221 ' _,--._ ', 222 ' ( {E} {E} ) ', 223 ' /[______]\\ ', 224 ' `` `` ', 225 ], 226 [ 227 ' ', 228 ' _,--._ ', 229 ' ( {E} {E} ) ', 230 ' /[======]\\ ', 231 ' `` `` ', 232 ], 233 ], 234 [snail]: [ 235 [ 236 ' ', 237 ' {E} .--. ', 238 ' \\ ( @ ) ', 239 ' \\_`--´ ', 240 ' ~~~~~~~ ', 241 ], 242 [ 243 ' ', 244 ' {E} .--. ', 245 ' | ( @ ) ', 246 ' \\_`--´ ', 247 ' ~~~~~~~ ', 248 ], 249 [ 250 ' ', 251 ' {E} .--. ', 252 ' \\ ( @ ) ', 253 ' \\_`--´ ', 254 ' ~~~~~~ ', 255 ], 256 ], 257 [ghost]: [ 258 [ 259 ' ', 260 ' .----. ', 261 ' / {E} {E} \\ ', 262 ' | | ', 263 ' ~`~``~`~ ', 264 ], 265 [ 266 ' ', 267 ' .----. ', 268 ' / {E} {E} \\ ', 269 ' | | ', 270 ' `~`~~`~` ', 271 ], 272 [ 273 ' ~ ~ ', 274 ' .----. ', 275 ' / {E} {E} \\ ', 276 ' | | ', 277 ' ~~`~~`~~ ', 278 ], 279 ], 280 [axolotl]: [ 281 [ 282 ' ', 283 '}~(______)~{', 284 '}~({E} .. {E})~{', 285 ' ( .--. ) ', 286 ' (_/ \\_) ', 287 ], 288 [ 289 ' ', 290 '~}(______){~', 291 '~}({E} .. {E}){~', 292 ' ( .--. ) ', 293 ' (_/ \\_) ', 294 ], 295 [ 296 ' ', 297 '}~(______)~{', 298 '}~({E} .. {E})~{', 299 ' ( -- ) ', 300 ' ~_/ \\_~ ', 301 ], 302 ], 303 [capybara]: [ 304 [ 305 ' ', 306 ' n______n ', 307 ' ( {E} {E} ) ', 308 ' ( oo ) ', 309 ' `------´ ', 310 ], 311 [ 312 ' ', 313 ' n______n ', 314 ' ( {E} {E} ) ', 315 ' ( Oo ) ', 316 ' `------´ ', 317 ], 318 [ 319 ' ~ ~ ', 320 ' u______n ', 321 ' ( {E} {E} ) ', 322 ' ( oo ) ', 323 ' `------´ ', 324 ], 325 ], 326 [cactus]: [ 327 [ 328 ' ', 329 ' n ____ n ', 330 ' | |{E} {E}| | ', 331 ' |_| |_| ', 332 ' | | ', 333 ], 334 [ 335 ' ', 336 ' ____ ', 337 ' n |{E} {E}| n ', 338 ' |_| |_| ', 339 ' | | ', 340 ], 341 [ 342 ' n n ', 343 ' | ____ | ', 344 ' | |{E} {E}| | ', 345 ' |_| |_| ', 346 ' | | ', 347 ], 348 ], 349 [robot]: [ 350 [ 351 ' ', 352 ' .[||]. ', 353 ' [ {E} {E} ] ', 354 ' [ ==== ] ', 355 ' `------´ ', 356 ], 357 [ 358 ' ', 359 ' .[||]. ', 360 ' [ {E} {E} ] ', 361 ' [ -==- ] ', 362 ' `------´ ', 363 ], 364 [ 365 ' * ', 366 ' .[||]. ', 367 ' [ {E} {E} ] ', 368 ' [ ==== ] ', 369 ' `------´ ', 370 ], 371 ], 372 [rabbit]: [ 373 [ 374 ' ', 375 ' (\\__/) ', 376 ' ( {E} {E} ) ', 377 ' =( .. )= ', 378 ' (")__(") ', 379 ], 380 [ 381 ' ', 382 ' (|__/) ', 383 ' ( {E} {E} ) ', 384 ' =( .. )= ', 385 ' (")__(") ', 386 ], 387 [ 388 ' ', 389 ' (\\__/) ', 390 ' ( {E} {E} ) ', 391 ' =( . . )= ', 392 ' (")__(") ', 393 ], 394 ], 395 [mushroom]: [ 396 [ 397 ' ', 398 ' .-o-OO-o-. ', 399 '(__________)', 400 ' |{E} {E}| ', 401 ' |____| ', 402 ], 403 [ 404 ' ', 405 ' .-O-oo-O-. ', 406 '(__________)', 407 ' |{E} {E}| ', 408 ' |____| ', 409 ], 410 [ 411 ' . o . ', 412 ' .-o-OO-o-. ', 413 '(__________)', 414 ' |{E} {E}| ', 415 ' |____| ', 416 ], 417 ], 418 [chonk]: [ 419 [ 420 ' ', 421 ' /\\ /\\ ', 422 ' ( {E} {E} ) ', 423 ' ( .. ) ', 424 ' `------´ ', 425 ], 426 [ 427 ' ', 428 ' /\\ /| ', 429 ' ( {E} {E} ) ', 430 ' ( .. ) ', 431 ' `------´ ', 432 ], 433 [ 434 ' ', 435 ' /\\ /\\ ', 436 ' ( {E} {E} ) ', 437 ' ( .. ) ', 438 ' `------´~ ', 439 ], 440 ], 441} 442 443const HAT_LINES: Record<Hat, string> = { 444 none: '', 445 crown: ' \\^^^/ ', 446 tophat: ' [___] ', 447 propeller: ' -+- ', 448 halo: ' ( ) ', 449 wizard: ' /^\\ ', 450 beanie: ' (___) ', 451 tinyduck: ' ,> ', 452} 453 454export function renderSprite(bones: CompanionBones, frame = 0): string[] { 455 const frames = BODIES[bones.species] 456 const body = frames[frame % frames.length]!.map(line => 457 line.replaceAll('{E}', bones.eye), 458 ) 459 const lines = [...body] 460 // Only replace with hat if line 0 is empty (some fidget frames use it for smoke etc) 461 if (bones.hat !== 'none' && !lines[0]!.trim()) { 462 lines[0] = HAT_LINES[bones.hat] 463 } 464 // Drop blank hat slot — wastes a row in the Card and ambient sprite when 465 // there's no hat and the frame isn't using it for smoke/antenna/etc. 466 // Only safe when ALL frames have blank line 0; otherwise heights oscillate. 467 if (!lines[0]!.trim() && frames.every(f => !f[0]!.trim())) lines.shift() 468 return lines 469} 470 471export function spriteFrameCount(species: Species): number { 472 return BODIES[species].length 473} 474 475export function renderFace(bones: CompanionBones): string { 476 const eye: Eye = bones.eye 477 switch (bones.species) { 478 case duck: 479 case goose: 480 return `(${eye}>` 481 case blob: 482 return `(${eye}${eye})` 483 case cat: 484 return `=${eye}ω${eye}=` 485 case dragon: 486 return `<${eye}~${eye}>` 487 case octopus: 488 return `~(${eye}${eye})~` 489 case owl: 490 return `(${eye})(${eye})` 491 case penguin: 492 return `(${eye}>)` 493 case turtle: 494 return `[${eye}_${eye}]` 495 case snail: 496 return `${eye}(@)` 497 case ghost: 498 return `/${eye}${eye}\\` 499 case axolotl: 500 return `}${eye}.${eye}{` 501 case capybara: 502 return `(${eye}oo${eye})` 503 case cactus: 504 return `|${eye} ${eye}|` 505 case robot: 506 return `[${eye}${eye}]` 507 case rabbit: 508 return `(${eye}..${eye})` 509 case mushroom: 510 return `|${eye} ${eye}|` 511 case chonk: 512 return `(${eye}.${eye})` 513 } 514}