ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/readable.C
(Generate patch)

Comparing deliantra/server/common/readable.C (file contents):
Revision 1.52 by root, Fri Nov 6 13:31:47 2009 UTC vs.
Revision 1.65 by root, Mon Oct 29 23:55:52 2012 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 6 * Copyright (©) 1992 Frank Tore Johansen
7 * 7 *
8 * Deliantra is free software: you can redistribute it and/or modify it under 8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * the terms of the Affero GNU General Public License as published by the 9 * the terms of the Affero GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your 10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the Affero GNU General Public License 18 * You should have received a copy of the Affero GNU General Public License
19 * and the GNU General Public License along with this program. If not, see 19 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>. 20 * <http://www.gnu.org/licenses/>.
21 * 21 *
22 * The authors can be reached via e-mail to <support@deliantra.net> 22 * The authors can be reached via e-mail to <support@deliantra.net>
23 */ 23 */
24 24
25/* This file contains code relevant to the BOOKS hack -- designed 25/* This file contains code relevant to the BOOKS hack -- designed
26 * to allow randomly occuring messages in non-magical texts. 26 * to allow randomly occuring messages in non-magical texts.
107 107
108/* these are needed for creation of a linked list of 108/* these are needed for creation of a linked list of
109 * pointers to all (hostile) monster objects */ 109 * pointers to all (hostile) monster objects */
110 110
111static int nrofmon = 0, need_to_write_bookarchive = 0; 111static int nrofmon = 0, need_to_write_bookarchive = 0;
112
113/* first_msg is the started of the linked list of messages as read from
114 * the messages file
115 */
116static linked_char *first_msg = NULL;
117 112
118/* 113/*
119 * Spellpath information 114 * Spellpath information
120 */ 115 */
121static uint32 spellpathdef[NRSPELLPATHS] = { 116static uint32 spellpathdef[NRSPELLPATHS] = {
406static const char *const book_descrpt[] = { 401static const char *const book_descrpt[] = {
407 "ancient", 402 "ancient",
408 "cryptic", 403 "cryptic",
409 "cryptical", 404 "cryptical",
410 "dusty", 405 "dusty",
411 "hiearchical", 406 "hierarchical",
412 "grizzled", 407 "grizzled",
413 "gold-guilt", 408 "gold-guilt",
414 "great", 409 "great",
415 "lost", 410 "lost",
416 "magnificent", 411 "magnificent",
509 * Start of misc. readable functions used by others functions in this file 504 * Start of misc. readable functions used by others functions in this file
510 * 505 *
511 *****************************************************************************/ 506 *****************************************************************************/
512 507
513static titlelist * 508static titlelist *
514get_empty_booklist (void) 509get_empty_booklist ()
515{ 510{
516 titlelist *bl = new titlelist; 511 titlelist *bl = new titlelist;
517 512
518 bl->number = 0; 513 bl->number = 0;
519 bl->first_book = NULL; 514 bl->first_book = NULL;
520 bl->next = NULL; 515 bl->next = NULL;
521 return bl; 516 return bl;
522} 517}
523 518
524static title * 519static title *
525get_empty_book (void) 520get_empty_book ()
526{ 521{
527 title *t = new title; 522 title *t = new title;
528 523
529 t->name = NULL; 524 t->name = NULL;
530 t->archname = NULL; 525 t->archname = NULL;
539/* get_titlelist() - returns pointer to the title list referanced by i */ 534/* get_titlelist() - returns pointer to the title list referanced by i */
540 535
541static titlelist * 536static titlelist *
542get_titlelist (int i) 537get_titlelist (int i)
543{ 538{
539 if (!booklist)
540 booklist = get_empty_booklist ();
541
544 titlelist *tl = booklist; 542 titlelist *tl = booklist;
545 int number = i; 543 int number = i;
546 544
547 if (number < 0) 545 if (number < 0)
548 return tl; 546 return tl;
551 { 549 {
552 if (!tl->next) 550 if (!tl->next)
553 tl->next = get_empty_booklist (); 551 tl->next = get_empty_booklist ();
554 552
555 tl = tl->next; 553 tl = tl->next;
556 number--; 554 --number;
557 } 555 }
558 556
559 return tl; 557 return tl;
560} 558}
561 559
571 char *tbuf, sbuf[12], buf[MAX_BUF]; 569 char *tbuf, sbuf[12], buf[MAX_BUF];
572 int number = 0; 570 int number = 0;
573 571
574 if (!buf1 || !buf2) 572 if (!buf1 || !buf2)
575 return 0; 573 return 0;
576 sprintf (buf, "%s", buf1); 574
577 sprintf (sbuf, "%s", buf2); 575 strcpy (buf, buf1);
576 strcpy (sbuf, buf2);
577
578 tbuf = strtok (buf, sbuf); 578 tbuf = strtok (buf, sbuf);
579 while (tbuf) 579 while (tbuf)
580 { 580 {
581 number++; 581 number++;
582 tbuf = strtok (NULL, sbuf); 582 tbuf = strtok (NULL, sbuf);
601 strcpy (rbuf, " "); 601 strcpy (rbuf, " ");
602 tbuf = strtok (buf, sbuf); 602 tbuf = strtok (buf, sbuf);
603 while (tbuf && i > 0) 603 while (tbuf && i > 0)
604 { 604 {
605 strcat (rbuf, tbuf); 605 strcat (rbuf, tbuf);
606
606 i--; 607 i--;
607 if (i == 1 && maxi > 1) 608 if (i == 1 && maxi > 1)
608 strcat (rbuf, " and "); 609 strcat (rbuf, " and ");
609 else if (i > 0 && maxi > 1) 610 else if (i > 0 && maxi > 1)
610 strcat (rbuf, ", "); 611 strcat (rbuf, ", ");
611 else 612 else
612 strcat (rbuf, "."); 613 strcat (rbuf, ".");
614
613 tbuf = strtok (NULL, sbuf); 615 tbuf = strtok (NULL, sbuf);
614 } 616 }
617
615 return (char *) rbuf; 618 return rbuf;
616} 619}
617 620
618/***************************************************************************** 621/*****************************************************************************
619 * 622 *
620 * Start of initialisation related functions. 623 * Start of initialisation related functions.
624/* init_book_archive() - if not called before, initialise the info list 627/* init_book_archive() - if not called before, initialise the info list
625 * This reads in the bookarch file into memory. bookarch is the file 628 * This reads in the bookarch file into memory. bookarch is the file
626 * created and updated across multiple runs of the program. 629 * created and updated across multiple runs of the program.
627 */ 630 */
628static void 631static void
629init_book_archive (void) 632init_book_archive ()
630{ 633{
631 FILE *fp;
632 int comp, nroftitle = 0; 634 int nroftitle = 0;
633 char buf[MAX_BUF], fname[MAX_BUF], *cp;
634 title *book = NULL;
635 titlelist *bl = get_empty_booklist (); 635 titlelist *bl = get_empty_booklist ();
636 static int did_init_barch;
637 636
638 if (did_init_barch) 637 object_thawer thawer (settings.localdir, "bookarch");
638
639 if (!thawer)
640 {
641 LOG (llevDebug, "could not read bookarch file\n");
639 return; 642 return;
640
641 did_init_barch = 1;
642
643 if (!booklist)
644 booklist = bl;
645
646 sprintf (fname, "%s/bookarch", settings.localdir);
647 LOG (llevDebug, " Reading bookarch from %s...\n", fname);
648
649 if ((fp = open_and_uncompress (fname, 0, &comp)) != NULL)
650 { 643 }
644
645 while (thawer.kw)
646 {
647 if (thawer.kw != KW_title)
648 if (!thawer.parse_error ("bookarch file"))
649 break;
650
651 title *book = get_empty_book (); /* init new book entry */
652 thawer.get (book->name);
653
651 int value, type = 0; 654 int type = -1;
652 size_t i;
653 655
654 while (fgets (buf, MAX_BUF, fp) != NULL) 656 for (;;)
655 { 657 {
656 if (*buf == '#') 658 thawer.next ();
657 continue; 659
658 if ((cp = strchr (buf, '\n')) != NULL) 660 switch (thawer.kw)
659 *cp = '\0';
660 cp = buf;
661 while (*cp == ' ') /* Skip blanks */
662 cp++;
663 if (!strncmp (cp, "title", 4))
664 { 661 {
665 book = get_empty_book (); /* init new book entry */ 662 case KW_type: thawer.get (type ); break;
666 book->name = strchr (cp, ' ') + 1; 663 case KW_authour: thawer.get (book->authour ); break;
667 type = -1; 664 case KW_arch: thawer.get (book->archname ); break;
668 nroftitle++; 665 case KW_level: thawer.get (book->level ); break;
669 continue; 666 case KW_size: thawer.get (book->size ); break;
670 } 667 case KW_index: thawer.get (book->msg_index); break;
671 if (!strncmp (cp, "authour", 4)) 668
672 { 669 case KW_end:
673 book->authour = strchr (cp, ' ') + 1;
674 }
675 if (!strncmp (cp, "arch", 4))
676 {
677 book->archname = strchr (cp, ' ') + 1;
678 }
679 else if (sscanf (cp, "level %d", &value))
680 {
681 book->level = (uint16) value;
682 }
683 else if (sscanf (cp, "type %d", &value))
684 {
685 type = (uint16) value;
686 }
687 else if (sscanf (cp, "size %d", &value))
688 {
689 book->size = (uint16) value;
690 }
691 else if (sscanf (cp, "index %d", &value))
692 {
693 book->msg_index = (uint16) value;
694 }
695 else if (!strncmp (cp, "end", 3))
696 { /* link it */ 670 /* link it */
697 bl = get_titlelist (type); 671 bl = get_titlelist (type);
698 book->next = bl->first_book; 672 book->next = bl->first_book;
699 bl->first_book = book; 673 bl->first_book = book;
700 bl->number++; 674 bl->number++;
675 ++nroftitle;
676 goto book_done;
677
678 default:
679 delete book;
680 goto book_done;
701 } 681 }
702 } 682 }
683
684book_done:
685 thawer.next ();
686 }
687
703 LOG (llevDebug, "book archives(used/avail): \n"); 688 LOG (llevDebug, "book archives(used/avail): \n");
689 int i;
704 for (bl = booklist, i = 0; bl != NULL && i < sizeof (max_titles) / sizeof (*max_titles); bl = bl->next, i++) 690 for (bl = booklist, i = 0; bl && i < sizeof (max_titles) / sizeof (*max_titles); bl = bl->next, i++)
705 {
706 LOG (llevDebug, " (%d/%d)\n", bl->number, max_titles[i]); 691 LOG (llevDebug, " (%d/%d)\n", bl->number, max_titles[i]);
707 }
708 close_and_delete (fp, comp);
709 }
710 692
711#ifdef BOOK_MSG_DEBUG
712 LOG (llevDebug, "init_book_archive() got %d titles.\n", nroftitle); 693 LOG (llevDebug, "init_book_archive() got %d titles.\n", nroftitle);
713#endif
714 LOG (llevDebug, " done.\n");
715} 694}
716 695
717/* init_mon_info() - creates the linked list of pointers to 696/* init_mon_info() - creates the linked list of pointers to
718 * monster archetype objects if not called previously 697 * monster archetype objects if not called previously
719 */ 698 */
749 * 728 *
750 * This is the function called by the main routine to initialise 729 * This is the function called by the main routine to initialise
751 * all the readable information. 730 * all the readable information.
752 */ 731 */
753void 732void
754init_readable (void) 733init_readable ()
755{ 734{
756 static int did_this; 735 static int did_this;
757 736
758 if (did_this) 737 if (did_this)
759 return; 738 return;
811 * is given is based on various criteria 790 * is given is based on various criteria
812 */ 791 */
813static void 792static void
814new_text_name (object *book, int msgtype) 793new_text_name (object *book, int msgtype)
815{ 794{
816 int nbr; 795 const char *name;
817 char name[MAX_BUF];
818 796
819 if (book->type != BOOK) 797 if (book->type != BOOK)
820 return; 798 return;
821 799
822 switch (msgtype) 800 switch (msgtype)
823 { 801 {
824 case 1: /*monster */ 802 case 1: /*monster */
825 nbr = sizeof (mon_book_name) / sizeof (char *); 803 name = mon_book_name[rndm (array_length (mon_book_name))];
826 assign (name, mon_book_name[rndm (nbr)]);
827 break; 804 break;
828 case 2: /*artifact */ 805 case 2: /*artifact */
829 nbr = sizeof (art_book_name) / sizeof (char *); 806 name = art_book_name[rndm (array_length (art_book_name))];
830 assign (name, art_book_name[rndm (nbr)]);
831 break; 807 break;
832 case 3: /*spellpath */ 808 case 3: /*spellpath */
833 nbr = sizeof (path_book_name) / sizeof (char *); 809 name = path_book_name[rndm (array_length (path_book_name))];
834 assign (name, path_book_name[rndm (nbr)]);
835 break; 810 break;
836 case 4: /*alchemy */ 811 case 4: /*alchemy */
837 nbr = sizeof (formula_book_name) / sizeof (char *); 812 name = formula_book_name[rndm (array_length (formula_book_name))];
838 assign (name, formula_book_name[rndm (nbr)]);
839 break; 813 break;
840 case 5: /*gods */ 814 case 5: /*gods */
841 nbr = sizeof (gods_book_name) / sizeof (char *); 815 name = gods_book_name[rndm (array_length (gods_book_name))];
842 assign (name, gods_book_name[rndm (nbr)]);
843 break; 816 break;
844 case 6: /*msg file */ 817 case 6: /*msg file */
845 default: 818 default:
846 if (book->weight > 2000) 819 if (book->weight > 2000)
847 { /* based on weight */ 820 { /* based on weight */
848 nbr = sizeof (heavy_book_name) / sizeof (char *); 821 name = heavy_book_name[rndm (array_length (heavy_book_name))];
849 assign (name, heavy_book_name[rndm (nbr)]);
850 } 822 }
851 else if (book->weight < 2001) 823 else if (book->weight < 2001)
852 { 824 {
853 nbr = sizeof (light_book_name) / sizeof (char *); 825 name = light_book_name[rndm (array_length (light_book_name))];
854 assign (name, light_book_name[rndm (nbr)]);
855 } 826 }
856 break; 827 break;
857 } 828 }
858 829
859 book->name = name; 830 book->name = name;
865 */ 836 */
866 837
867static void 838static void
868add_author (object *op, int msgtype) 839add_author (object *op, int msgtype)
869{ 840{
870 char title[MAX_BUF], name[MAX_BUF]; 841 const char *name;
871 int nbr = sizeof (book_author) / sizeof (char *);
872 842
873 if (msgtype < 0 || strlen (op->msg) < 5) 843 if (msgtype < 0 || strlen (op->msg) < 5)
874 return; 844 return;
875 845
876 switch (msgtype) 846 switch (msgtype)
877 { 847 {
878 case 1: /* monster */ 848 case 1: /* monster */
879 nbr = sizeof (mon_author) / sizeof (char *); 849 name = mon_author[rndm (array_length (mon_author))];
880 assign (name, mon_author[rndm (nbr)]);
881 break; 850 break;
882 case 2: /* artifacts */ 851 case 2: /* artifacts */
883 nbr = sizeof (art_author) / sizeof (char *); 852 name = art_author[rndm (array_length (art_author))];
884 assign (name, art_author[rndm (nbr)]);
885 break; 853 break;
886 case 3: /* spellpath */ 854 case 3: /* spellpath */
887 nbr = sizeof (path_author) / sizeof (char *); 855 name = path_author[rndm (array_length (path_author))];
888 assign (name, path_author[rndm (nbr)]);
889 break; 856 break;
890 case 4: /* alchemy */ 857 case 4: /* alchemy */
891 nbr = sizeof (formula_author) / sizeof (char *); 858 name = formula_author[rndm (array_length (formula_author))];
892 assign (name, formula_author[rndm (nbr)]);
893 break; 859 break;
894 case 5: /* gods */ 860 case 5: /* gods */
895 nbr = sizeof (gods_author) / sizeof (char *); 861 name = gods_author[rndm (array_length (gods_author))];
896 assign (name, gods_author[rndm (nbr)]);
897 break; 862 break;
898 case 6: /* msg file */ 863 case 6: /* msg file */
899 default: 864 default:
900 assign (name, book_author[rndm (nbr)]); 865 name = book_author[rndm (array_length (book_author))];
901 } 866 }
902 867
903 sprintf (title, "of %s", name); 868 op->title = format ("of %s", name);
904 op->title = title;
905} 869}
906 870
907/* unique_book() - check to see if the book title/msg is unique. We 871/* unique_book() - check to see if the book title/msg is unique. We
908 * go through the entire list of possibilities each time. If we find 872 * go through the entire list of possibilities each time. If we find
909 * a match, then unique_book returns true (because inst unique). 873 * a match, then unique_book returns true (because inst unique).
991 */ 955 */
992 956
993 if ((strlen (book->msg) > 5) && (t = find_title (book, msgtype))) 957 if ((strlen (book->msg) > 5) && (t = find_title (book, msgtype)))
994 { 958 {
995 /* alter book properties */ 959 /* alter book properties */
996 if (object *tmpbook = get_archetype (t->archname)) 960 if (object *tmpbook = archetype::get (t->archname))
997 { 961 {
998 tmpbook->msg = book->msg; 962 tmpbook->msg = book->msg;
999 tmpbook->copy_to (book); 963 tmpbook->copy_to (book);
1000 tmpbook->destroy (); 964 tmpbook->destroy ();
1001 } 965 }
1059#endif 1023#endif
1060 /* restore old book properties here */ 1024 /* restore old book properties here */
1061 book->title = old_title; 1025 book->title = old_title;
1062 1026
1063 if (rndm (4)) 1027 if (rndm (4))
1064 {
1065 /* Lets give the book a description to individualize it some */ 1028 /* Lets give the book a description to individualize it some */
1066 char new_name[MAX_BUF];
1067
1068 snprintf (new_name, MAX_BUF, "%s %s", book_descrpt[rndm (nbr)], old_name); 1029 book->name = format ("%s %s", book_descrpt[rndm (nbr)], old_name);
1069
1070 book->name = new_name;
1071 }
1072 else 1030 else
1073 {
1074 book->name = old_name; 1031 book->name = old_name;
1075 }
1076 } 1032 }
1077 else if (book->title && strlen (book->msg) > 5) 1033 else if (book->title && strlen (book->msg) > 5)
1078 { /* archive if long msg texts */ 1034 { /* archive if long msg texts */
1079 add_book_to_list (book, msgtype); 1035 add_book_to_list (book, msgtype);
1080 } 1036 }
1270 * for that type exists! 1226 * for that type exists!
1271 */ 1227 */
1272 i = 0; 1228 i = 0;
1273 do 1229 do
1274 { 1230 {
1275 index = rndm (sizeof (art_name_array) / sizeof (arttypename)); 1231 index = rndm (array_length (art_name_array));
1276 type = art_name_array[index].type; 1232 type = art_name_array[index].type;
1277 al = find_artifactlist (type); 1233 al = find_artifactlist (type);
1278 i++; 1234 i++;
1279 } 1235 }
1280 while ((al == NULL) && (i < 10)); 1236 while ((al == NULL) && (i < 10));
1353 1309
1354 /* properties of the artifact */ 1310 /* properties of the artifact */
1355 tmp = object::create (); 1311 tmp = object::create ();
1356 add_abilities (tmp, art->item); 1312 add_abilities (tmp, art->item);
1357 tmp->type = type; 1313 tmp->type = type;
1358 SET_FLAG (tmp, FLAG_IDENTIFIED); 1314 tmp->set_flag (FLAG_IDENTIFIED);
1359 if ((ch = describe_item (tmp, 0)) && strlen (ch) > 1) 1315 if ((ch = describe_item (tmp, 0)) && strlen (ch) > 1)
1360 buf << "\rProperties of this artifact include:\r" << ch << "\n"; 1316 buf << "\rProperties of this artifact include:\r" << ch << "\n";
1361 1317
1362 tmp->destroy (); 1318 tmp->destroy ();
1363 1319
1379static char * 1335static char *
1380spellpath_msg (int level) 1336spellpath_msg (int level)
1381{ 1337{
1382 static dynbuf_text buf; buf.clear (); 1338 static dynbuf_text buf; buf.clear ();
1383 1339
1384 static char retbuf[BOOK_BUF];
1385 char tmpbuf[BOOK_BUF];
1386 int path = rndm (NRSPELLPATHS), prayers = rndm (2); 1340 int path = rndm (NRSPELLPATHS), prayers = rndm (2);
1387 uint32 pnum = (path == -1) ? PATH_NULL : spellpathdef[path]; 1341 uint32 pnum = (path == -1) ? PATH_NULL : spellpathdef[path];
1388 archetype *at; 1342 archetype *at;
1389 1343
1390 /* Preamble */ 1344 /* Preamble */
1600 int i; 1554 int i;
1601 1555
1602 if (enemy && !(god->path_denied & PATH_TURNING)) 1556 if (enemy && !(god->path_denied & PATH_TURNING))
1603 if ((i = nstrtok (enemy, ",")) > 0) 1557 if ((i = nstrtok (enemy, ",")) > 0)
1604 { 1558 {
1605 char tmpbuf[MAX_BUF];
1606
1607 buf << "The holy words of " << name 1559 buf << "The holy words of " << name
1608 << " have the power to slay creatures belonging to the "; 1560 << " have the power to slay creatures belonging to the ";
1609 1561
1610 if (i > 1) 1562 if (i > 1)
1611 buf << "following races:" << strtoktolin (enemy, ","); 1563 buf << "following races:" << strtoktolin (enemy, ",");
1687 { /* spell paths */ 1639 { /* spell paths */
1688 //TODO: 1640 //TODO:
1689 int has_effect = 0, tmpvar; 1641 int has_effect = 0, tmpvar;
1690 char tmpbuf[MAX_BUF]; 1642 char tmpbuf[MAX_BUF];
1691 1643
1692 sprintf (tmpbuf, "\n");
1693 sprintf (tmpbuf, "It is rarely known fact that the priests of %s\n", name); 1644 sprintf (tmpbuf, "It is rarely known fact that the priests of %s\n", name);
1694 strcat (tmpbuf, "are mystically transformed. Effects of this include:\n"); 1645 strcat (tmpbuf, "are mystically transformed. Effects of this include:\n");
1695 1646
1696 if ((tmpvar = god->path_attuned)) 1647 if ((tmpvar = god->path_attuned))
1697 { 1648 {
1806 * Writeback routine for updating the bookarchive. 1757 * Writeback routine for updating the bookarchive.
1807 * 1758 *
1808 ****************************************************************************/ 1759 ****************************************************************************/
1809/* write_book_archive() - write out the updated book archive */ 1760/* write_book_archive() - write out the updated book archive */
1810void 1761void
1811write_book_archive (void) 1762write_book_archive ()
1812{ 1763{
1813 FILE *fp; 1764 FILE *fp;
1814 int index = 0; 1765 int index = 0;
1815 char fname[MAX_BUF]; 1766 char fname[MAX_BUF];
1816 title *book = NULL; 1767 title *book = NULL;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines