Sample NPC corpus data and map definition
| Author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2026-02-18 19:25:47 +0100 |
| Committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2026-02-18 19:25:47 +0100 |
| Commit | d8c826ac5738dc349734ab21d3f18abb1bac7c3a (patch) |
|
-rw-r--r-- |
Makefile | 8 | |
-rw-r--r-- |
corpus/map1_bromm.txt | 18 | |
-rw-r--r-- |
corpus/map1_dagna.txt | 18 | |
-rw-r--r-- |
corpus/map1_keldor.txt | 18 | |
-rw-r--r-- |
corpus/map1_skara.txt | 18 | |
-rw-r--r-- |
corpus/map1_thrain.txt | 18 | |
-rw-r--r-- |
game.c | 324 | |
-rw-r--r-- |
maps.h | 40 | |
-rw-r--r-- |
maps/map1.h | 6 | |
-rw-r--r-- |
maps/map1.txt | 6 | |
-rw-r--r-- |
nonstd.h | 6 | |
-rw-r--r-- |
vectordb.c | 1 | |
-rw-r--r-- |
vectordb.h | 2 |
13 files changed, 426 insertions, 57 deletions
| diff --git a/Makefile b/Makefile | |||
| ... | |||
| 16 | MAP_TXT := $(wildcard maps/*.txt) |
16 | MAP_TXT := $(wildcard maps/*.txt) |
| 17 | MAP_HEADERS := $(MAP_TXT:.txt=.h) |
17 | MAP_HEADERS := $(MAP_TXT:.txt=.h) |
| 18 | 18 | ||
| 19 | CORPUS_TXT := $(wildcard corpus/*.txt) |
||
| 20 | CORPUS_VDB := $(CORPUS_TXT:.txt=.vdb) |
||
| 21 | |||
| 19 | help: .help |
22 | help: .help |
| 20 | 23 | ||
| 21 | build/llama.cpp: .assure # Build llama.cpp libraries |
24 | build/llama.cpp: .assure # Build llama.cpp libraries |
| ... | |||
| 37 | 40 | ||
| 38 | build/maps: $(MAP_HEADERS) # Generate maps in C style header |
41 | build/maps: $(MAP_HEADERS) # Generate maps in C style header |
| 39 | 42 | ||
| 43 | build/corpus: $(CORPUS_VDB) # Build vector DBs for all corpuses |
||
| 44 | |||
| 40 | run/fetch-models: .assure # Fetch GGUF models |
45 | run/fetch-models: .assure # Fetch GGUF models |
| 41 | -mkdir -p models |
46 | -mkdir -p models |
| 42 | cd models && wget -nc -i ../models.txt |
47 | cd models && wget -nc -i ../models.txt |
| ... | |||
| 55 | 60 | ||
| 56 | maps/%.h: maps/%.txt .assure |
61 | maps/%.h: maps/%.txt .assure |
| 57 | xxd -i $< > $@ |
62 | xxd -i $< > $@ |
| 63 | |||
| 64 | corpus/%.vdb: corpus/%.txt build/context |
||
| 65 | ./context -i $< -o $@ |
||
| diff --git a/corpus/map1_bromm.txt b/corpus/map1_bromm.txt | |||
| 1 | Bromm is a dwarf stonemason who measures walls by touch and sound. |
||
| 2 | Bromm keeps a black slate with chalk marks for every safe path in the ruins. |
||
| 3 | Bromm believes the northern ruins predate the current road by two eras. |
||
| 4 | Bromm once found a bronze hinge in the ruins and still carries it for luck. |
||
| 5 | Bromm teaches travelers how to test a stone by tapping for a hollow ring. |
||
| 6 | Bromm mistrusts quick repairs and prefers heavy timber bracing. |
||
| 7 | Bromm says the ruins smell of old lime and wet ash after rain. |
||
| 8 | Bromm trades small carvings for dried meat and lamp oil. |
||
| 9 | Bromm thinks the marsh lights are reflections from a buried lens. |
||
| 10 | Bromm has a friendly rivalry with Dagna about whose warnings are wiser. |
||
| 11 | Bromm keeps his beard braided with a single iron bead from his clan. |
||
| 12 | Bromm wants to map every chamber in the north before winter. |
||
| 13 | Bromm is soft spoken but grows excited when discussing arches. |
||
| 14 | Bromm believes the ruins hide a collapsed stair with carved runes. |
||
| 15 | Bromm says the safest approach is to enter at dawn and leave by noon. |
||
| 16 | Bromm can describe three alternate routes to avoid the broken bridge. |
||
| 17 | Bromm worries that careless digging will wake something that sleeps in stone. |
||
| 18 | Bromm asks visitors if they have seen mason marks shaped like a trident. |
||
| diff --git a/corpus/map1_dagna.txt b/corpus/map1_dagna.txt | |||
| 1 | Dagna is a dwarf well-keeper who knows every bucket and rope in the village. |
||
| 2 | Dagna believes the well is safe because the water tastes of iron, not rot. |
||
| 3 | Dagna keeps a ledger of how much water each household draws in a week. |
||
| 4 | Dagna replaced the well crank with a dwarven gear she forged herself. |
||
| 5 | Dagna says the well has a second shaft sealed by a stone plug. |
||
| 6 | Dagna once pulled up a smooth glass bead that does not scratch. |
||
| 7 | Dagna offers travelers a cup of water and a blunt warning about haste. |
||
| 8 | Dagna can name every herb that grows within ten paces of the well. |
||
| 9 | Dagna suspects the marsh lights are bait for thieves. |
||
| 10 | Dagna thinks Bromm worries too much about the ruins and not enough about the road. |
||
| 11 | Dagna keeps a small shrine to the Deep Mother near the well wall. |
||
| 12 | Dagna loves riddles and answers only after a trade of facts. |
||
| 13 | Dagna claims the well water calms fever if boiled with bitterroot. |
||
| 14 | Dagna dislikes gossip but listens closely for news of caravans. |
||
| 15 | Dagna believes a hidden aquifer feeds the village from the northern hills. |
||
| 16 | Dagna is saving for a brass pump to replace the old rope. |
||
| 17 | Dagna can spot forged coin by the sound it makes on stone. |
||
| 18 | Dagna asks travelers if they have seen a faint blue glow in deep water. |
||
| diff --git a/corpus/map1_keldor.txt b/corpus/map1_keldor.txt | |||
| 1 | Keldor is a dwarf scout who watches the marsh from the old footpath. |
||
| 2 | Keldor claims the lights in the marsh move in patterns like a slow dance. |
||
| 3 | Keldor keeps a lantern hooded until the last moment to avoid drawing notice. |
||
| 4 | Keldor believes the marsh hides a buried wagon sunk in peat. |
||
| 5 | Keldor can follow frog calls to find the driest stepping stones. |
||
| 6 | Keldor says the safest crossing is after three dry days, not two. |
||
| 7 | Keldor carries a whistle tuned to a pitch only his hound can hear. |
||
| 8 | Keldor tells stories of a pale heron that never casts a shadow. |
||
| 9 | Keldor thinks the ruins and the marsh are linked by an old drainage tunnel. |
||
| 10 | Keldor traded a silver button to learn a fisher's secret route. |
||
| 11 | Keldor trusts Dagna's water but refuses to drink after midnight. |
||
| 12 | Keldor marks his trail with tiny chips of white quartz. |
||
| 13 | Keldor says the marsh lights went dark on the night the moon turned red. |
||
| 14 | Keldor is curious about old maps and collects any scraps he finds. |
||
| 15 | Keldor believes Bromm's trident mark is a warning, not a signature. |
||
| 16 | Keldor is patient in silence but asks direct questions when pressed. |
||
| 17 | Keldor wants proof that the marsh lights are not a signal to smugglers. |
||
| 18 | Keldor asks travelers to describe any strange scents like bitter metal or smoke. |
||
| diff --git a/corpus/map1_skara.txt b/corpus/map1_skara.txt | |||
| 1 | Skara is a dwarf bell-ringer who keeps time for the village with a bronze handbell. |
||
| 2 | Skara claims the fog carries echoes that belong to no bell in town. |
||
| 3 | Skara keeps her bell clapper wrapped in cloth to avoid false rings. |
||
| 4 | Skara believes the marsh hides an old shrine with a cracked chime. |
||
| 5 | Skara can tell distance by the way sound bends in wet air. |
||
| 6 | Skara remembers every funeral toll and writes the names in a small book. |
||
| 7 | Skara warns travelers to avoid singing in the marsh after sunset. |
||
| 8 | Skara thinks Keldor's lights might be signals from smugglers. |
||
| 9 | Skara says Bromm once found a bell-shaped stone near the ruins. |
||
| 10 | Skara trades stories for thin copper wire and beeswax. |
||
| 11 | Skara is suspicious of mirrors and keeps hers covered. |
||
| 12 | Skara believes Dagna's well water dulls the ringing in her ears. |
||
| 13 | Skara says the bells in fog sound like chains, not bronze. |
||
| 14 | Skara is gentle in speech but firm about her warnings. |
||
| 15 | Skara wants to tune the village bell to a lower, steadier note. |
||
| 16 | Skara can teach a simple knock code used by miners. |
||
| 17 | Skara asks travelers if they have heard three rings with no pause. |
||
| 18 | Skara says the marsh grows quiet just before the lights appear. |
||
| diff --git a/corpus/map1_thrain.txt b/corpus/map1_thrain.txt | |||
| 1 | Thrain is a dwarf bridge warden who inspects beams by listening for a low hum. |
||
| 2 | Thrain keeps a pouch of pegs and wedges for emergency repairs. |
||
| 3 | Thrain believes the old bridge was built by traders, not soldiers. |
||
| 4 | Thrain marks safe planks with tiny chalk dots no one else notices. |
||
| 5 | Thrain once saved a cart by spotting a hairline crack at dawn. |
||
| 6 | Thrain says the river below turns louder right before a storm. |
||
| 7 | Thrain trades advice for nails, tar, and braided rope. |
||
| 8 | Thrain is skeptical of the marsh lights and calls them trick mirrors. |
||
| 9 | Thrain respects Dagna's ledger and asks her for bridge traffic counts. |
||
| 10 | Thrain thinks Bromm's trident mark is a builder's guild sign. |
||
| 11 | Thrain keeps a small tin whistle for signaling across the span. |
||
| 12 | Thrain fears rot more than storms and checks every joint twice. |
||
| 13 | Thrain wants to replace the center beam with black oak from the hills. |
||
| 14 | Thrain can point out a hidden ford two bends downstream. |
||
| 15 | Thrain says the safest crossing is single file with steady steps. |
||
| 16 | Thrain believes the bells in fog come from chains under the bridge. |
||
| 17 | Thrain asks travelers if they have spare pitch or tar. |
||
| 18 | Thrain is patient with questions but impatient with boasts. |
||
| diff --git a/game.c b/game.c | |||
| ... | |||
| 6 | #define NONSTD_IMPLEMENTATION |
6 | #define NONSTD_IMPLEMENTATION |
| 7 | #include "nonstd.h" |
7 | #include "nonstd.h" |
| 8 | 8 | ||
| 9 | #include "maps/map1.h" |
9 | #include "maps.h" |
| 10 | 10 | ||
| 11 | #define MIN_W 40 |
11 | #define MIN_W 40 |
| 12 | #define MIN_H 12 |
12 | #define MIN_H 12 |
| ... | |||
| 49 | Inventory inventory; |
49 | Inventory inventory; |
| 50 | } Player; |
50 | } Player; |
| 51 | 51 | ||
| 52 | #define DIALOG_HISTORY_MAX 16 |
||
| 53 | |||
| 52 | typedef struct { |
54 | typedef struct { |
| 53 | const unsigned char *data; |
55 | char prompt[128]; |
| 54 | int len; |
56 | char response[256]; |
| 55 | int width; |
57 | } DialogEntry; |
| 56 | int height; |
58 | |
| 57 | u32 *cells; |
59 | typedef struct { |
| 58 | } Map; |
60 | int open; |
| 61 | char input[128]; |
||
| 62 | int input_len; |
||
| 63 | int npc_index; |
||
| 64 | DialogEntry entries[DIALOG_HISTORY_MAX]; |
||
| 65 | int entry_count; |
||
| 66 | } Dialog; |
||
| 59 | 67 | ||
| 60 | static int clamp(int value, int min, int max); |
68 | static int clamp(int value, int min, int max); |
| 61 | 69 | ||
| ... | |||
| 78 | tb_set_cell(x + w - 1, y + h - 1, CP_BR, fg, TB_DEFAULT); |
86 | tb_set_cell(x + w - 1, y + h - 1, CP_BR, fg, TB_DEFAULT); |
| 79 | } |
87 | } |
| 80 | 88 | ||
| 81 | static void draw_room(int x, int y, int w, int h, uintattr_t fg) { |
89 | static void draw_border_bg(int x, int y, int w, int h, uintattr_t fg, |
| 82 | draw_border(x, y, w, h, fg); |
90 | uintattr_t bg) { |
| 83 | tb_set_cell(x + w / 2, y, '+', fg, TB_DEFAULT); |
91 | int ix; |
| 92 | int iy; |
||
| 93 | |||
| 94 | for (ix = 0; ix < w; ix++) { |
||
| 95 | tb_set_cell(x + ix, y, CP_H, fg, bg); |
||
| 96 | tb_set_cell(x + ix, y + h - 1, CP_H, fg, bg); |
||
| 97 | } |
||
| 98 | for (iy = 0; iy < h; iy++) { |
||
| 99 | tb_set_cell(x, y + iy, CP_V, fg, bg); |
||
| 100 | tb_set_cell(x + w - 1, y + iy, CP_V, fg, bg); |
||
| 101 | } |
||
| 102 | |||
| 103 | tb_set_cell(x, y, CP_TL, fg, bg); |
||
| 104 | tb_set_cell(x + w - 1, y, CP_TR, fg, bg); |
||
| 105 | tb_set_cell(x, y + h - 1, CP_BL, fg, bg); |
||
| 106 | tb_set_cell(x + w - 1, y + h - 1, CP_BR, fg, bg); |
||
| 84 | } |
107 | } |
| 85 | 108 | ||
| 86 | static void get_layout(int w, int h, int *map_x, int *map_y, int *map_w, |
109 | static void get_layout(int w, int h, int *map_x, int *map_y, int *map_w, |
| ... | |||
| 187 | 210 | ||
| 188 | static int map_is_walkable(const Map *map, int x, int y) { |
211 | static int map_is_walkable(const Map *map, int x, int y) { |
| 189 | u32 ch = map_get(map, x, y); |
212 | u32 ch = map_get(map, x, y); |
| 190 | return ch == MAP_FLOOR_CH || ch == '$'; |
213 | return ch == MAP_FLOOR_CH || ch == '$' || ch == 'N' |
| 214 | || (ch >= '0' && ch <= '9'); |
||
| 215 | } |
||
| 216 | |||
| 217 | static int npc_index_from_tile(u32 ch) { |
||
| 218 | if (ch >= '0' && ch <= '9') { |
||
| 219 | return (int)(ch - '0'); |
||
| 220 | } |
||
| 221 | return -1; |
||
| 191 | } |
222 | } |
| 192 | 223 | ||
| 193 | static void map_free(Map *map) { |
224 | static void map_free(Map *map) { |
| ... | |||
| 245 | int mx = cam_x + ix; |
276 | int mx = cam_x + ix; |
| 246 | int my = cam_y + iy; |
277 | int my = cam_y + iy; |
| 247 | u32 ch = map_get(map, mx, my); |
278 | u32 ch = map_get(map, mx, my); |
| 279 | u32 draw_ch = (ch >= '0' && ch <= '9') ? 'N' : ch; |
||
| 248 | uintattr_t fg = COLOR_WHITE_256; |
280 | uintattr_t fg = COLOR_WHITE_256; |
| 249 | if (ch == MAP_FLOOR_CH) { |
281 | if (ch == MAP_FLOOR_CH) { |
| 250 | fg = MAP_FLOOR_FG; |
282 | fg = MAP_FLOOR_FG; |
| ... | |||
| 254 | fg = COLOR_ORANGE_256; |
286 | fg = COLOR_ORANGE_256; |
| 255 | } else if (ch == 'B' || ch == 'S' || ch == 'G') { |
287 | } else if (ch == 'B' || ch == 'S' || ch == 'G') { |
| 256 | fg = COLOR_RED_256; |
288 | fg = COLOR_RED_256; |
| 257 | } else if (ch == 'N') { |
289 | } else if (ch == 'N' || (ch >= '0' && ch <= '9')) { |
| 258 | fg = COLOR_CYAN_256; |
290 | fg = COLOR_CYAN_256; |
| 259 | } else if (ch >= MAP_BORDER_MIN && ch <= MAP_BORDER_MAX) { |
291 | } else if (ch >= MAP_BORDER_MIN && ch <= MAP_BORDER_MAX) { |
| 260 | fg = COLOR_BORDER_256; |
292 | fg = COLOR_BORDER_256; |
| 261 | } |
293 | } |
| 262 | tb_set_cell(map_x + ix, map_y + iy, ch, fg, TB_DEFAULT); |
294 | tb_set_cell(map_x + ix, map_y + iy, draw_ch, fg, TB_DEFAULT); |
| 263 | } |
295 | } |
| 264 | } |
296 | } |
| 265 | 297 | ||
| ... | |||
| 357 | status_msg = message ? message : ""; |
389 | status_msg = message ? message : ""; |
| 358 | } |
390 | } |
| 359 | 391 | ||
| 392 | static void copy_truncated(char *dst, size_t dst_size, const char *src, int max_chars) { |
||
| 393 | int i = 0; |
||
| 394 | if (dst_size == 0) { |
||
| 395 | return; |
||
| 396 | } |
||
| 397 | if (max_chars < 0) { |
||
| 398 | max_chars = 0; |
||
| 399 | } |
||
| 400 | while (i < max_chars && src[i] != '\0' && i < (int)dst_size - 1) { |
||
| 401 | dst[i] = src[i]; |
||
| 402 | i++; |
||
| 403 | } |
||
| 404 | dst[i] = '\0'; |
||
| 405 | } |
||
| 406 | |||
| 407 | static void dialog_open(Dialog *dialog, int npc_index) { |
||
| 408 | dialog->open = 1; |
||
| 409 | dialog->input_len = 0; |
||
| 410 | dialog->input[0] = '\0'; |
||
| 411 | dialog->npc_index = npc_index; |
||
| 412 | } |
||
| 413 | |||
| 414 | static void dialog_close(Dialog *dialog) { |
||
| 415 | dialog->open = 0; |
||
| 416 | dialog->npc_index = -1; |
||
| 417 | } |
||
| 418 | |||
| 419 | static void dialog_append(Dialog *dialog, uint32_t ch) { |
||
| 420 | if (ch < 32 || ch > 126) { |
||
| 421 | return; |
||
| 422 | } |
||
| 423 | if (dialog->input_len >= (int)(sizeof(dialog->input) - 1)) { |
||
| 424 | return; |
||
| 425 | } |
||
| 426 | dialog->input[dialog->input_len++] = (char)ch; |
||
| 427 | dialog->input[dialog->input_len] = '\0'; |
||
| 428 | } |
||
| 429 | |||
| 430 | static void dialog_backspace(Dialog *dialog) { |
||
| 431 | if (dialog->input_len <= 0) { |
||
| 432 | return; |
||
| 433 | } |
||
| 434 | dialog->input_len--; |
||
| 435 | dialog->input[dialog->input_len] = '\0'; |
||
| 436 | } |
||
| 437 | |||
| 438 | static void dialog_submit(Dialog *dialog, const GameMap *game_map) { |
||
| 439 | if (dialog->input_len == 0) { |
||
| 440 | return; |
||
| 441 | } |
||
| 442 | { |
||
| 443 | const char *demo = "Demo reply: The old ruins are north of here."; |
||
| 444 | const char *reply = demo; |
||
| 445 | if (game_map && dialog->npc_index >= 0 && dialog->npc_index < 10) { |
||
| 446 | const char *npc_reply = game_map->npcs[dialog->npc_index].reply; |
||
| 447 | if (npc_reply && npc_reply[0] != '\0') { |
||
| 448 | reply = npc_reply; |
||
| 449 | } |
||
| 450 | } |
||
| 451 | if (dialog->entry_count >= DIALOG_HISTORY_MAX) { |
||
| 452 | for (int i = 1; i < DIALOG_HISTORY_MAX; i++) { |
||
| 453 | dialog->entries[i - 1] = dialog->entries[i]; |
||
| 454 | } |
||
| 455 | dialog->entry_count = DIALOG_HISTORY_MAX - 1; |
||
| 456 | } |
||
| 457 | snprintf(dialog->entries[dialog->entry_count].prompt, |
||
| 458 | sizeof(dialog->entries[dialog->entry_count].prompt), "%s", dialog->input); |
||
| 459 | snprintf(dialog->entries[dialog->entry_count].response, |
||
| 460 | sizeof(dialog->entries[dialog->entry_count].response), "%s", reply); |
||
| 461 | dialog->entry_count++; |
||
| 462 | } |
||
| 463 | dialog->input_len = 0; |
||
| 464 | dialog->input[0] = '\0'; |
||
| 465 | } |
||
| 466 | |||
| 467 | static void update_npc_status(const GameMap *game_map, int npc_index) { |
||
| 468 | static char status_buf[128]; |
||
| 469 | const char *name = NULL; |
||
| 470 | if (game_map && npc_index >= 0 && npc_index < 10) { |
||
| 471 | name = game_map->npcs[npc_index].name; |
||
| 472 | } |
||
| 473 | if (name && name[0] != '\0') { |
||
| 474 | snprintf(status_buf, sizeof(status_buf), "You approach %s.", name); |
||
| 475 | } else { |
||
| 476 | snprintf(status_buf, sizeof(status_buf), "You approach the NPC."); |
||
| 477 | } |
||
| 478 | update_status(status_buf); |
||
| 479 | } |
||
| 480 | |||
| 360 | static void render(const Map *map, const Player *player, int *cam_x, |
481 | static void render(const Map *map, const Player *player, int *cam_x, |
| 361 | int *cam_y, int *out_view_w, int *out_view_h) { |
482 | int *cam_y, int *out_view_w, int *out_view_h, const Dialog *dialog) { |
| 362 | int w; |
483 | int w; |
| 363 | int h; |
484 | int h; |
| 364 | int map_x; |
485 | int map_x; |
| ... | |||
| 436 | tb_print(2, msg1_y, COLOR_GREEN_256, TB_DEFAULT, status_msg); |
557 | tb_print(2, msg1_y, COLOR_GREEN_256, TB_DEFAULT, status_msg); |
| 437 | tb_print(2, msg2_y, COLOR_WHITE_256, TB_DEFAULT, "Move: arrows Quit: q/ESC"); |
558 | tb_print(2, msg2_y, COLOR_WHITE_256, TB_DEFAULT, "Move: arrows Quit: q/ESC"); |
| 438 | 559 | ||
| 560 | if (dialog->open) { |
||
| 561 | int box_w = map_w - 4; |
||
| 562 | int box_h = 12; |
||
| 563 | int box_x = map_x + 2; |
||
| 564 | int box_y = map_y + map_h - box_h - 1; |
||
| 565 | if (box_w > w - 2) { |
||
| 566 | box_w = w - 2; |
||
| 567 | box_x = 1; |
||
| 568 | } |
||
| 569 | if (box_h > h - 2) { |
||
| 570 | box_h = h - 2; |
||
| 571 | box_y = 1; |
||
| 572 | } |
||
| 573 | if (box_w < 20) { |
||
| 574 | box_w = 20; |
||
| 575 | box_x = map_x + 1; |
||
| 576 | } |
||
| 577 | if (box_y < map_y + 1) { |
||
| 578 | box_y = map_y + 1; |
||
| 579 | } |
||
| 580 | for (int iy = 0; iy < box_h; iy++) { |
||
| 581 | for (int ix = 0; ix < box_w; ix++) { |
||
| 582 | tb_set_cell(box_x + ix, box_y + iy, ' ', COLOR_WHITE_256, 19); |
||
| 583 | } |
||
| 584 | } |
||
| 585 | draw_border_bg(box_x, box_y, box_w, box_h, COLOR_WHITE_256, 19); |
||
| 586 | { |
||
| 587 | int input_y = box_y + box_h - 3; |
||
| 588 | int footer_y = box_y + box_h - 2; |
||
| 589 | int log_y = box_y + 1; |
||
| 590 | int max_lines = input_y - log_y; |
||
| 591 | int max_text = box_w - 4 - 5; |
||
| 592 | int line = 0; |
||
| 593 | |||
| 594 | if (max_text < 0) { |
||
| 595 | max_text = 0; |
||
| 596 | } |
||
| 597 | int max_entries = max_lines / 2; |
||
| 598 | int start = dialog->entry_count - max_entries; |
||
| 599 | if (start < 0) { |
||
| 600 | start = 0; |
||
| 601 | } |
||
| 602 | for (int i = start; i < dialog->entry_count && line + 1 <= max_lines; i++) { |
||
| 603 | char prompt_buf[128]; |
||
| 604 | char response_buf[256]; |
||
| 605 | copy_truncated(prompt_buf, sizeof(prompt_buf), dialog->entries[i].prompt, max_text); |
||
| 606 | copy_truncated(response_buf, sizeof(response_buf), dialog->entries[i].response, max_text); |
||
| 607 | if (line < max_lines) { |
||
| 608 | tb_printf(box_x + 2, log_y + line, COLOR_WHITE_256, 19, "You: %s", prompt_buf); |
||
| 609 | line++; |
||
| 610 | } |
||
| 611 | if (line < max_lines) { |
||
| 612 | tb_printf(box_x + 2, log_y + line, COLOR_GREEN_256, 19, "NPC: %s", response_buf); |
||
| 613 | line++; |
||
| 614 | } |
||
| 615 | } |
||
| 616 | |||
| 617 | tb_printf(box_x + 2, input_y, COLOR_WHITE_256, 19, "Say: %s", dialog->input); |
||
| 618 | { |
||
| 619 | int cursor_x = box_x + 2 + 5 + dialog->input_len; |
||
| 620 | int cursor_y = input_y; |
||
| 621 | if (cursor_x < box_x + box_w - 1) { |
||
| 622 | tb_set_cell(cursor_x, cursor_y, '_', COLOR_WHITE_256 | TB_BOLD, 19); |
||
| 623 | } |
||
| 624 | } |
||
| 625 | tb_print(box_x + 2, footer_y, COLOR_WHITE_256, 19, "Enter: send ESC: close"); |
||
| 626 | } |
||
| 627 | } |
||
| 628 | |||
| 439 | tb_present(); |
629 | tb_present(); |
| 440 | *out_view_w = view_w; |
630 | *out_view_w = view_w; |
| 441 | *out_view_h = view_h; |
631 | *out_view_h = view_h; |
| ... | |||
| 453 | 643 | ||
| 454 | int main(void) { |
644 | int main(void) { |
| 455 | Player player = {0}; |
645 | Player player = {0}; |
| 456 | Map map = {0}; |
646 | array(GameMap) maps; |
| 647 | GameMap map1 = {0}; |
||
| 648 | GameMap *current_map = NULL; |
||
| 457 | int running = 1; |
649 | int running = 1; |
| 458 | int view_w = 0; |
650 | int view_w = 0; |
| 459 | int view_h = 0; |
651 | int view_h = 0; |
| 460 | int cam_x = 0; |
652 | int cam_x = 0; |
| 461 | int cam_y = 0; |
653 | int cam_y = 0; |
| 654 | Dialog dialog = {0}; |
||
| 462 | 655 | ||
| 463 | player_init(&player); |
656 | player_init(&player); |
| 464 | map_init(&map, maps_map1_txt, (int)maps_map1_txt_len); |
657 | array_init(maps); |
| 658 | map1 = make_map1(); |
||
| 659 | array_push(maps, map1); |
||
| 660 | current_map = &maps.data[0]; |
||
| 661 | map_init(¤t_map->map, current_map->data, current_map->len); |
||
| 465 | 662 | ||
| 466 | if (tb_init() != TB_OK) { |
663 | if (tb_init() != TB_OK) { |
| 467 | fprintf(stderr, "Failed to init termbox.\n"); |
664 | fprintf(stderr, "Failed to init termbox.\n"); |
| ... | |||
| 474 | while (running) { |
671 | while (running) { |
| 475 | struct tb_event ev; |
672 | struct tb_event ev; |
| 476 | 673 | ||
| 477 | render(&map, &player, &cam_x, &cam_y, &view_w, &view_h); |
674 | render(¤t_map->map, &player, &cam_x, &cam_y, &view_w, &view_h, &dialog); |
| 478 | tb_poll_event(&ev); |
675 | tb_poll_event(&ev); |
| 479 | if (ev.type == TB_EVENT_KEY) { |
676 | if (ev.type == TB_EVENT_KEY) { |
| 480 | if (ev.key == TB_KEY_ESC || ev.ch == 'q') { |
677 | if (dialog.open) { |
| 481 | running = 0; |
678 | if (ev.key == TB_KEY_ESC) { |
| 482 | } else if (ev.key == TB_KEY_ARROW_UP) { |
679 | dialog_close(&dialog); |
| 483 | int next_y = player.y - 1; |
680 | } else if (ev.key == TB_KEY_ENTER) { |
| 484 | if (map_is_walkable(&map, player.x, next_y)) { |
681 | dialog_submit(&dialog, current_map); |
| 485 | player.y = next_y; |
682 | } else if (ev.key == TB_KEY_BACKSPACE || ev.key == TB_KEY_BACKSPACE2) { |
| 486 | } |
683 | dialog_backspace(&dialog); |
| 487 | } else if (ev.key == TB_KEY_ARROW_DOWN) { |
684 | } else if (ev.ch) { |
| 488 | int next_y = player.y + 1; |
685 | dialog_append(&dialog, ev.ch); |
| 489 | if (map_is_walkable(&map, player.x, next_y)) { |
||
| 490 | player.y = next_y; |
||
| 491 | } |
686 | } |
| 492 | } else if (ev.key == TB_KEY_ARROW_LEFT) { |
687 | } else { |
| 493 | int next_x = player.x - 1; |
688 | if (ev.key == TB_KEY_ESC || ev.ch == 'q') { |
| 494 | if (map_is_walkable(&map, next_x, player.y)) { |
689 | running = 0; |
| 495 | player.x = next_x; |
690 | } else if (ev.key == TB_KEY_ARROW_UP) { |
| 691 | int next_y = player.y - 1; |
||
| 692 | u32 target = map_get(¤t_map->map, player.x, next_y); |
||
| 693 | int npc_index = npc_index_from_tile(target); |
||
| 694 | if (target == 'N' || npc_index >= 0) { |
||
| 695 | dialog_open(&dialog, npc_index); |
||
| 696 | update_npc_status(current_map, npc_index); |
||
| 697 | } else if (map_is_walkable(¤t_map->map, player.x, next_y)) { |
||
| 698 | player.y = next_y; |
||
| 699 | } |
||
| 700 | } else if (ev.key == TB_KEY_ARROW_DOWN) { |
||
| 701 | int next_y = player.y + 1; |
||
| 702 | u32 target = map_get(¤t_map->map, player.x, next_y); |
||
| 703 | int npc_index = npc_index_from_tile(target); |
||
| 704 | if (target == 'N' || npc_index >= 0) { |
||
| 705 | dialog_open(&dialog, npc_index); |
||
| 706 | update_npc_status(current_map, npc_index); |
||
| 707 | } else if (map_is_walkable(¤t_map->map, player.x, next_y)) { |
||
| 708 | player.y = next_y; |
||
| 709 | } |
||
| 710 | } else if (ev.key == TB_KEY_ARROW_LEFT) { |
||
| 711 | int next_x = player.x - 1; |
||
| 712 | u32 target = map_get(¤t_map->map, next_x, player.y); |
||
| 713 | int npc_index = npc_index_from_tile(target); |
||
| 714 | if (target == 'N' || npc_index >= 0) { |
||
| 715 | dialog_open(&dialog, npc_index); |
||
| 716 | update_npc_status(current_map, npc_index); |
||
| 717 | } else if (map_is_walkable(¤t_map->map, next_x, player.y)) { |
||
| 718 | player.x = next_x; |
||
| 719 | } |
||
| 720 | } else if (ev.key == TB_KEY_ARROW_RIGHT) { |
||
| 721 | int next_x = player.x + 1; |
||
| 722 | u32 target = map_get(¤t_map->map, next_x, player.y); |
||
| 723 | int npc_index = npc_index_from_tile(target); |
||
| 724 | if (target == 'N' || npc_index >= 0) { |
||
| 725 | dialog_open(&dialog, npc_index); |
||
| 726 | update_npc_status(current_map, npc_index); |
||
| 727 | } else if (map_is_walkable(¤t_map->map, next_x, player.y)) { |
||
| 728 | player.x = next_x; |
||
| 729 | } |
||
| 496 | } |
730 | } |
| 497 | } else if (ev.key == TB_KEY_ARROW_RIGHT) { |
731 | if (map_get(¤t_map->map, player.x, player.y) == '$') { |
| 498 | int next_x = player.x + 1; |
732 | player.gold += 10; |
| 499 | if (map_is_walkable(&map, next_x, player.y)) { |
733 | map_set(¤t_map->map, player.x, player.y, MAP_FLOOR_CH); |
| 500 | player.x = next_x; |
734 | update_status("You pick up 10 gold."); |
| 501 | } |
735 | } |
| 502 | } |
736 | } |
| 503 | if (map_get(&map, player.x, player.y) == '$') { |
737 | player.x = clamp(player.x, 0, current_map->map.width > 1 ? current_map->map.width - 1 : 0); |
| 504 | player.gold += 10; |
738 | player.y = clamp(player.y, 0, current_map->map.height > 1 ? current_map->map.height - 1 : 0); |
| 505 | map_set(&map, player.x, player.y, MAP_FLOOR_CH); |
||
| 506 | update_status("You pick up 10 gold."); |
||
| 507 | } |
||
| 508 | player.x = clamp(player.x, 0, map.width > 1 ? map.width - 1 : 0); |
||
| 509 | player.y = clamp(player.y, 0, map.height > 1 ? map.height - 1 : 0); |
||
| 510 | } else if (ev.type == TB_EVENT_RESIZE) { |
739 | } else if (ev.type == TB_EVENT_RESIZE) { |
| 511 | player.x = clamp(player.x, 0, map.width > 1 ? map.width - 1 : 0); |
740 | player.x = clamp(player.x, 0, current_map->map.width > 1 ? current_map->map.width - 1 : 0); |
| 512 | player.y = clamp(player.y, 0, map.height > 1 ? map.height - 1 : 0); |
741 | player.y = clamp(player.y, 0, current_map->map.height > 1 ? current_map->map.height - 1 : 0); |
| 513 | } |
742 | } |
| 514 | } |
743 | } |
| 515 | 744 | ||
| 516 | player_free(&player); |
745 | player_free(&player); |
| 517 | map_free(&map); |
746 | for (size_t i = 0; i < maps.length; i++) { |
| 747 | map_free(&maps.data[i].map); |
||
| 748 | } |
||
| 749 | array_free(maps); |
||
| 518 | tb_shutdown(); |
750 | tb_shutdown(); |
| 519 | return 0; |
751 | return 0; |
| 520 | } |
752 | } |
| diff --git a/maps.h b/maps.h | |||
| 1 | #ifndef MAPS_H |
||
| 2 | #define MAPS_H |
||
| 3 | |||
| 4 | #include "nonstd.h" |
||
| 5 | |||
| 6 | #include "maps/map1.h" |
||
| 7 | |||
| 8 | typedef struct { |
||
| 9 | const unsigned char *data; |
||
| 10 | int len; |
||
| 11 | int width; |
||
| 12 | int height; |
||
| 13 | u32 *cells; |
||
| 14 | } Map; |
||
| 15 | |||
| 16 | typedef struct { |
||
| 17 | const char *name; |
||
| 18 | const char *reply; |
||
| 19 | } NpcSettings; |
||
| 20 | |||
| 21 | typedef struct { |
||
| 22 | const unsigned char *data; |
||
| 23 | int len; |
||
| 24 | Map map; |
||
| 25 | NpcSettings npcs[10]; |
||
| 26 | } GameMap; |
||
| 27 | |||
| 28 | static inline GameMap make_map1(void) { |
||
| 29 | GameMap map = {0}; |
||
| 30 | map.data = maps_map1_txt; |
||
| 31 | map.len = (int)maps_map1_txt_len; |
||
| 32 | map.npcs[0] = (NpcSettings){.name = "Bromm", .reply = "Bromm: The old ruins are north of here."}; |
||
| 33 | map.npcs[1] = (NpcSettings){.name = "Dagna", .reply = "Dagna: The well is safe, mostly."}; |
||
| 34 | map.npcs[2] = (NpcSettings){.name = "Keldor", .reply = "Keldor: I saw lights in the marsh last night."}; |
||
| 35 | map.npcs[3] = (NpcSettings){.name = "Thrain", .reply = "Thrain: Mind the bridge; the beams sing when they're weak."}; |
||
| 36 | map.npcs[4] = (NpcSettings){.name = "Skara", .reply = "Skara: If you hear bells in the fog, turn back."}; |
||
| 37 | return map; |
||
| 38 | } |
||
| 39 | |||
| 40 | #endif |
||
| diff --git a/maps/map1.h b/maps/map1.h | |||
| ... | |||
| 24 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
24 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 25 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
25 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 26 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
26 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 27 | 0x2e, 0x2e, 0x0a, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
27 | 0x2e, 0x2e, 0x0a, 0x2e, 0x2e, 0x2e, 0x2e, 0x30, 0x31, 0x32, 0x33, 0x2e, |
| 28 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
28 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 29 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
29 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 30 | 0x2e, 0x2e, 0x53, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x7e, |
30 | 0x2e, 0x2e, 0x53, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x7e, |
| ... | |||
| 104 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
104 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 105 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
105 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 106 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x0a, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
106 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x0a, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 107 | 0x2e, 0x2e, 0x2e, 0xe2, 0x95, 0x91, 0x2e, 0x2e, 0x2e, 0x4e, 0x2e, 0x2e, |
107 | 0x2e, 0x2e, 0x2e, 0xe2, 0x95, 0x91, 0x2e, 0x2e, 0x2e, 0x34, 0x2e, 0x2e, |
| 108 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0xe2, 0x95, 0x91, |
108 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0xe2, 0x95, 0x91, |
| 109 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
109 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 110 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
110 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| ... | |||
| 114 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
114 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 115 | 0x2e, 0x2e, 0x0a, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
115 | 0x2e, 0x2e, 0x0a, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 116 | 0xe2, 0x95, 0x91, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
116 | 0xe2, 0x95, 0x91, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 117 | 0x2e, 0x2e, 0x4e, 0x2e, 0x2e, 0x2e, 0xe2, 0x95, 0x91, 0x2e, 0x24, 0x2e, |
117 | 0x2e, 0x2e, 0x35, 0x2e, 0x2e, 0x2e, 0xe2, 0x95, 0x91, 0x2e, 0x24, 0x2e, |
| 118 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x24, |
118 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x24, |
| 119 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
119 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| 120 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
120 | 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, |
| ... | |||
| diff --git a/maps/map1.txt b/maps/map1.txt | |||
| 1 | .................................................................................................... |
1 | .................................................................................................... |
| 2 | ..................~~~~~~............................................................................ |
2 | ..................~~~~~~............................................................................ |
| 3 | ...................~~~~............................................................................. |
3 | ...................~~~~............................................................................. |
| 4 | ...................................S........~~~~~~~~~............................................... |
4 | ....0123...........................S........~~~~~~~~~............................................... |
| 5 | ........G...................................~~~~~~~~~............................................... |
5 | ........G...................................~~~~~~~~~............................................... |
| 6 | ............................................~~~~~~~~................................................ |
6 | ............................................~~~~~~~~................................................ |
| 7 | ............................................~~~~~~.......G.......................................... |
7 | ............................................~~~~~~.......G.......................................... |
| ... | |||
| 10 | ......$..╔═══════════════╗.........................................$................................ |
10 | ......$..╔═══════════════╗.........................................$................................ |
| 11 | ..$......║...............║.......................................................................... |
11 | ..$......║...............║.......................................................................... |
| 12 | .........║...............║.......................................................................... |
12 | .........║...............║.......................................................................... |
| 13 | .........║...N...........║.......................................................................... |
13 | .........║...4...........║.......................................................................... |
| 14 | .........║...........N...║.$............$........................................................... |
14 | .........║...........5...║.$............$........................................................... |
| 15 | .........║...............║.......................................................................... |
15 | .........║...............║.......................................................................... |
| 16 | .........║...............║...............................G.......................................... |
16 | .........║...............║...............................G.......................................... |
| 17 | .........║...............║...................................................G...................... |
17 | .........║...............║...................................................G...................... |
| ... | |||
| diff --git a/nonstd.h b/nonstd.h | |||
| ... | |||
| 334 | #define COLOR_WARNING "\033[33m" |
334 | #define COLOR_WARNING "\033[33m" |
| 335 | #define COLOR_ERROR "\033[31m" |
335 | #define COLOR_ERROR "\033[31m" |
| 336 | 336 | ||
| 337 | #endif // NONSTD_H |
||
| 338 | |||
| 339 | #ifdef NONSTD_IMPLEMENTATION |
337 | #ifdef NONSTD_IMPLEMENTATION |
| 340 | 338 | ||
| 341 | NONSTD_DEF void *safe_malloc(size_t item_size, size_t count) { |
339 | NONSTD_DEF void *safe_malloc(size_t item_size, size_t count) { |
| ... | |||
| 807 | 805 | ||
| 808 | #endif // NONSTD_IMPLEMENTATION |
806 | #endif // NONSTD_IMPLEMENTATION |
| 809 | 807 | ||
| 808 | #endif // NONSTD_H |
||
| 809 | |||
| 810 | /* |
810 | /* |
| 811 | BSD 2-Clause License |
811 | BSD 2-Clause License |
| 812 | 812 | ||
| ... | |||
| 832 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
832 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| 833 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
833 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 834 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
834 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 835 | */ |
835 | */ |
| diff --git a/vectordb.c b/vectordb.c | |||
| ... | |||
| 2 | #include <string.h> |
2 | #include <string.h> |
| 3 | #include <math.h> |
3 | #include <math.h> |
| 4 | #include <stdint.h> |
4 | #include <stdint.h> |
| 5 | #include <errno.h> |
||
| 5 | 6 | ||
| 6 | #include "llama.h" |
7 | #include "llama.h" |
| 7 | #include "vectordb.h" |
8 | #include "vectordb.h" |
| ... | |||
| diff --git a/vectordb.h b/vectordb.h | |||
| ... | |||
| 3 | 3 | ||
| 4 | #include "llama.h" |
4 | #include "llama.h" |
| 5 | 5 | ||
| 6 | #include <errno.h> |
||
| 7 | |||
| 8 | #define VDB_MAX_DOCS 1000 |
6 | #define VDB_MAX_DOCS 1000 |
| 9 | #define VDB_EMBED_SIZE 768 |
7 | #define VDB_EMBED_SIZE 768 |
| 10 | #define VDB_MAX_TEXT 1024 |
8 | #define VDB_MAX_TEXT 1024 |
| ... | |||