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 (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team |
4 | * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2002 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 2002 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 1992 Frank Tore Johansen |
7 | * Copyright (©) 1992 Frank Tore Johansen |
7 | * |
8 | * |
8 | * Deliantra is free software: you can redistribute it and/or modify it under |
9 | * 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 |
10 | * the terms of the Affero GNU General Public License as published by the |
… | |
… | |
31 | #include <global.h> |
32 | #include <global.h> |
32 | #include <book.h> |
33 | #include <book.h> |
33 | #include <living.h> |
34 | #include <living.h> |
34 | #include <spells.h> |
35 | #include <spells.h> |
35 | |
36 | |
36 | /* Define this if you want to archive book titles by contents. |
37 | /* Define this if you want to archive book titles by contents. |
37 | * This option should enforce UNIQUE combinations of titles,authors and |
38 | * This option should enforce UNIQUE combinations of titles,authors and |
38 | * msg contents during and *between* game sessions. |
39 | * msg contents during and *between* game sessions. |
39 | * Note: a slight degeneracy exists since books are archived based on an integer |
40 | * Note: a slight degeneracy exists since books are archived based on an integer |
40 | * index value calculated from the message text (similar to alchemy formulae). |
41 | * index value calculated from the message text (similar to alchemy formulae). |
41 | * Sometimes two widely different messages have the same index value (rare). In |
42 | * Sometimes two widely different messages have the same index value (rare). In |
42 | * this case, it is possible to occasionally generate 2 books with same title and |
43 | * this case, it is possible to occasionally generate 2 books with same title and |
43 | * different message content. Not really a bug, but rather a feature. This action |
44 | * different message content. Not really a bug, but rather a feature. This action |
44 | * should keeps player on their toes ;). |
45 | * should keeps player on their toes ;). |
45 | * Also, note that there is *finite* space available for archiving message and titles. |
46 | * Also, note that there is *finite* space available for archiving message and titles. |
46 | * Once this space is used, books will stop being archived. Not a serious problem |
47 | * Once this space is used, books will stop being archived. Not a serious problem |
47 | * under the current regime, since there are generally fewer possible (random) |
48 | * under the current regime, since there are generally fewer possible (random) |
48 | * messages than space available on the titlelists. |
49 | * messages than space available on the titlelists. |
49 | * One exception (for sure) are the monster messages. But no worries, you should |
50 | * One exception (for sure) are the monster messages. But no worries, you should |
50 | * see all of the monster info in some order (but not all possble combinations) |
51 | * see all of the monster info in some order (but not all possble combinations) |
51 | * before the monster titlelist space is run out. You can increase titlelist |
52 | * before the monster titlelist space is run out. You can increase titlelist |
52 | * space by increasing the array sizes for the monster book_authours and book_names |
53 | * space by increasing the array sizes for the monster book_authours and book_names |
53 | * (see max_titles[] array and include/read.h). Since the unique_book algorthm is |
54 | * (see max_titles[] array and include/read.h). Since the unique_book algorthm is |
54 | * kinda stupid, this program *may* slow down program execution if defined (but I don't |
55 | * kinda stupid, this program *may* slow down program execution if defined (but I don't |
55 | * think its a significant problem, at least, I have no problems running this option |
56 | * think its a significant problem, at least, I have no problems running this option |
56 | * on a Sparc 10! Also, once archive title lists are filled and/or all possible msg |
57 | * on a Sparc 10! Also, once archive title lists are filled and/or all possible msg |
57 | * combinations have been generated, unique_book isnt called anymore. It takes 5-10 |
58 | * combinations have been generated, unique_book isnt called anymore. It takes 5-10 |
58 | * sessions for this to happen). |
59 | * sessions for this to happen). |
59 | * Final note: the game remembers book/title/msg combinations from reading the |
60 | * Final note: the game remembers book/title/msg combinations from reading the |
60 | * file lib/bookarch. If you REMOVE this file, you will lose your archive. So |
61 | * file lib/bookarch. If you REMOVE this file, you will lose your archive. So |
61 | * be sure to copy it over to the new lib directory when you change versions. |
62 | * be sure to copy it over to the new lib directory when you change versions. |
62 | * -b.t. |
63 | * -b.t. |
63 | */ |
64 | */ |
64 | |
65 | |
65 | /* This flag is useful to see what kind of output messages are created */ |
66 | /* This flag is useful to see what kind of output messages are created */ |
66 | |
67 | |
… | |
… | |
555 | } |
556 | } |
556 | |
557 | |
557 | return tl; |
558 | return tl; |
558 | } |
559 | } |
559 | |
560 | |
560 | /* HANDMADE STRING FUNCTIONS.., perhaps these belong in another file |
561 | /* HANDMADE STRING FUNCTIONS.., perhaps these belong in another file |
561 | * (shstr.c ?), but the quantity BOOK_BUF will need to be defined. */ |
562 | * (shstr.c ?), but the quantity BOOK_BUF will need to be defined. */ |
562 | |
563 | |
563 | /* nstrtok() - simple routine to return the number of list |
564 | /* nstrtok() - simple routine to return the number of list |
564 | * items in buf1 as separated by the value of buf2 |
565 | * items in buf1 as separated by the value of buf2 |
565 | */ |
566 | */ |
… | |
… | |
691 | LOG (llevDebug, " (%d/%d)\n", bl->number, max_titles[i]); |
692 | LOG (llevDebug, " (%d/%d)\n", bl->number, max_titles[i]); |
692 | |
693 | |
693 | LOG (llevDebug, "init_book_archive() got %d titles.\n", nroftitle); |
694 | LOG (llevDebug, "init_book_archive() got %d titles.\n", nroftitle); |
694 | } |
695 | } |
695 | |
696 | |
696 | /* init_mon_info() - creates the linked list of pointers to |
697 | /* init_mon_info() - creates the linked list of pointers to |
697 | * monster archetype objects if not called previously |
698 | * monster archetype objects if not called previously |
698 | */ |
699 | */ |
699 | static void |
700 | static void |
700 | init_mon_info () |
701 | init_mon_info () |
701 | { |
702 | { |
… | |
… | |
721 | } |
722 | } |
722 | |
723 | |
723 | LOG (llevDebug, "init_mon_info() got %d monsters\n", nrofmon); |
724 | LOG (llevDebug, "init_mon_info() got %d monsters\n", nrofmon); |
724 | } |
725 | } |
725 | |
726 | |
726 | /* init_readable() - initialise linked lists utilized by |
727 | /* init_readable() - initialise linked lists utilized by |
727 | * message functions in tailor_readable_ob() |
728 | * message functions in tailor_readable_ob() |
728 | * |
729 | * |
729 | * This is the function called by the main routine to initialise |
730 | * This is the function called by the main routine to initialise |
730 | * all the readable information. |
731 | * all the readable information. |
731 | */ |
732 | */ |
732 | void |
733 | void |
… | |
… | |
782 | |
783 | |
783 | return t; |
784 | return t; |
784 | } |
785 | } |
785 | |
786 | |
786 | /* new_text_name() - Only for objects of type BOOK. SPELLBOOK stuff is |
787 | /* new_text_name() - Only for objects of type BOOK. SPELLBOOK stuff is |
787 | * handled directly in change_book_name(). Names are based on text |
788 | * handled directly in change_book_name(). Names are based on text |
788 | * msgtype |
789 | * msgtype |
789 | * this sets book book->name based on msgtype given. What name |
790 | * this sets book book->name based on msgtype given. What name |
790 | * is given is based on various criteria |
791 | * is given is based on various criteria |
791 | */ |
792 | */ |
792 | static void |
793 | static void |
… | |
… | |
814 | case 5: /*gods */ |
815 | case 5: /*gods */ |
815 | name = gods_book_name[rndm (array_length (gods_book_name))]; |
816 | name = gods_book_name[rndm (array_length (gods_book_name))]; |
816 | break; |
817 | break; |
817 | case 6: /*msg file */ |
818 | case 6: /*msg file */ |
818 | default: |
819 | default: |
819 | if (book->weight > 2000) |
820 | name = book->weight > 2000 /* based on weight */ |
820 | { /* based on weight */ |
|
|
821 | name = heavy_book_name[rndm (array_length (heavy_book_name))]; |
821 | ? heavy_book_name [rndm (array_length (heavy_book_name))] |
822 | } |
|
|
823 | else if (book->weight < 2001) |
|
|
824 | { |
|
|
825 | name = light_book_name[rndm (array_length (light_book_name))]; |
822 | : light_book_name [rndm (array_length (light_book_name))]; |
826 | } |
|
|
827 | break; |
823 | break; |
828 | } |
824 | } |
829 | |
825 | |
830 | book->name = name; |
826 | book->name = name; |
831 | } |
827 | } |
832 | |
828 | |
833 | /* add_book_author() |
829 | /* add_book_author() |
834 | * A lot like new_text_name above, but instead chooses an author |
830 | * A lot like new_text_name above, but instead chooses an author |
835 | * and sets op->title to that value |
831 | * and sets op->title to that value |
836 | */ |
832 | */ |
837 | |
833 | |
838 | static void |
834 | static void |
… | |
… | |
866 | } |
862 | } |
867 | |
863 | |
868 | op->title = format ("of %s", name); |
864 | op->title = format ("of %s", name); |
869 | } |
865 | } |
870 | |
866 | |
871 | /* unique_book() - check to see if the book title/msg is unique. We |
867 | /* unique_book() - check to see if the book title/msg is unique. We |
872 | * go through the entire list of possibilities each time. If we find |
868 | * go through the entire list of possibilities each time. If we find |
873 | * a match, then unique_book returns true (because inst unique). |
869 | * a match, then unique_book returns true (because inst unique). |
874 | */ |
870 | */ |
875 | |
871 | |
876 | static int |
872 | static int |
… | |
… | |
923 | #endif |
919 | #endif |
924 | |
920 | |
925 | } |
921 | } |
926 | |
922 | |
927 | |
923 | |
928 | /* change_book() - give a new, fancier name to generated |
924 | /* change_book() - give a new, fancier name to generated |
929 | * objects of type BOOK and SPELLBOOK. |
925 | * objects of type BOOK and SPELLBOOK. |
930 | * Aug 96 I changed this so we will attempt to create consistent |
926 | * Aug 96 I changed this so we will attempt to create consistent |
931 | * authour/title and message content for BOOKs. Also, we will |
927 | * authour/title and message content for BOOKs. Also, we will |
932 | * alter books that match archive entries to the archival |
928 | * alter books that match archive entries to the archival |
933 | * levels and architypes. -b.t. |
929 | * levels and architypes. -b.t. |
934 | */ |
930 | */ |
935 | |
931 | |
936 | #define MAX_TITLE_CHECK 20 |
932 | #define MAX_TITLE_CHECK 20 |
937 | |
933 | |
938 | static void |
934 | static void |
… | |
… | |
948 | title *t = NULL; |
944 | title *t = NULL; |
949 | int tries = 0; |
945 | int tries = 0; |
950 | |
946 | |
951 | /* look to see if our msg already been archived. If so, alter |
947 | /* look to see if our msg already been archived. If so, alter |
952 | * the book to match the archival text. If we fail to match, |
948 | * the book to match the archival text. If we fail to match, |
953 | * then we archive the new title/name/msg combo if there is |
949 | * then we archive the new title/name/msg combo if there is |
954 | * room on the titlelist. |
950 | * room on the titlelist. |
955 | */ |
951 | */ |
956 | |
952 | |
957 | if ((strlen (book->msg) > 5) && (t = find_title (book, msgtype))) |
953 | if ((strlen (book->msg) > 5) && (t = find_title (book, msgtype))) |
958 | { |
954 | { |
959 | /* alter book properties */ |
955 | /* alter book properties */ |
… | |
… | |
1009 | |
1005 | |
1010 | /* Now deal with 2 cases. |
1006 | /* Now deal with 2 cases. |
1011 | * 1)If no space for a new title exists lets just restore |
1007 | * 1)If no space for a new title exists lets just restore |
1012 | * the old book properties. Remember, if the book had |
1008 | * the old book properties. Remember, if the book had |
1013 | * matchd an older entry on the titlelist, we shouldnt |
1009 | * matchd an older entry on the titlelist, we shouldnt |
1014 | * have called this routine in the first place! |
1010 | * have called this routine in the first place! |
1015 | * 2) If we got a unique title, we need to add it to |
1011 | * 2) If we got a unique title, we need to add it to |
1016 | * the list. |
1012 | * the list. |
1017 | */ |
1013 | */ |
1018 | |
1014 | |
1019 | if (tries == MAX_TITLE_CHECK || numb == maxnames) |
1015 | if (tries == MAX_TITLE_CHECK || numb == maxnames) |
… | |
… | |
1053 | |
1049 | |
1054 | /***************************************************************************** |
1050 | /***************************************************************************** |
1055 | * Monster msg generation code. |
1051 | * Monster msg generation code. |
1056 | ****************************************************************************/ |
1052 | ****************************************************************************/ |
1057 | |
1053 | |
1058 | /* get_random_mon() - returns a random monster slected from linked |
1054 | /* get_random_mon() - returns a random monster slected from linked |
1059 | * list of all monsters in the current game. If level is non-zero, |
1055 | * list of all monsters in the current game. If level is non-zero, |
1060 | * then only monsters greater than that level will be returned. |
1056 | * then only monsters greater than that level will be returned. |
1061 | * Changed 971225 to be greater than equal to level passed. Also |
1057 | * Changed 971225 to be greater than equal to level passed. Also |
1062 | * made choosing by level more random. |
1058 | * made choosing by level more random. |
1063 | */ |
1059 | */ |
… | |
… | |
1089 | } |
1085 | } |
1090 | |
1086 | |
1091 | /* Case where we are searching by level. Redone 971225 to be clearer |
1087 | /* Case where we are searching by level. Redone 971225 to be clearer |
1092 | * and more random. Before, it looks like it took a random monster from |
1088 | * and more random. Before, it looks like it took a random monster from |
1093 | * the list, and then returned the first monster after that which was |
1089 | * the list, and then returned the first monster after that which was |
1094 | * appropriate level. This wasn't very random because if you had a |
1090 | * appropriate level. This wasn't very random because if you had a |
1095 | * bunch of low level monsters and then a high level one, if the random |
1091 | * bunch of low level monsters and then a high level one, if the random |
1096 | * determine took one of the low level ones, it would just forward to the |
1092 | * determine took one of the low level ones, it would just forward to the |
1097 | * high level one and return that. Thus, monsters that immediatly followed |
1093 | * high level one and return that. Thus, monsters that immediatly followed |
1098 | * a bunch of low level monsters would be more heavily returned. It also |
1094 | * a bunch of low level monsters would be more heavily returned. It also |
1099 | * means some of the dragons would be poorly represented, since they |
1095 | * means some of the dragons would be poorly represented, since they |
… | |
… | |
1162 | else |
1158 | else |
1163 | return first_mon_info->ob; |
1159 | return first_mon_info->ob; |
1164 | |
1160 | |
1165 | } |
1161 | } |
1166 | |
1162 | |
1167 | /* mon_info_msg() - generate a message detailing the properties |
1163 | /* mon_info_msg() - generate a message detailing the properties |
1168 | * of a randomly selected monster. |
1164 | * of a randomly selected monster. |
1169 | */ |
1165 | */ |
1170 | static const char * |
1166 | static const char * |
1171 | mon_info_msg (int level) |
1167 | mon_info_msg (int level) |
1172 | { |
1168 | { |
1173 | static dynbuf_text buf; buf.clear (); |
1169 | static dynbuf_text buf; buf.clear (); |
1174 | |
1170 | |
1175 | /*preamble */ |
1171 | /*preamble */ |
1176 | buf << "This beastiary contains:\n"; |
1172 | buf << "This beastiary contains:\n"; |
1177 | |
1173 | |
1178 | /* lets print info on as many monsters as will fit in our |
1174 | /* lets print info on as many monsters as will fit in our |
1179 | * document. |
1175 | * document. |
1180 | * 8-96 Had to change this a bit, otherwise there would |
1176 | * 8-96 Had to change this a bit, otherwise there would |
1181 | * have been an impossibly large number of combinations |
1177 | * have been an impossibly large number of combinations |
1182 | * of text! (and flood out the available number of titles |
1178 | * of text! (and flood out the available number of titles |
1183 | * in the archive in a snap!) -b.t. |
1179 | * in the archive in a snap!) -b.t. |
1184 | */ |
1180 | */ |
1185 | object *tmp = get_random_mon (level * 3); |
1181 | object *tmp = get_random_mon (level * 3); |
1186 | while (tmp && buf.size () < BOOK_BUF) |
1182 | while (tmp && buf.size () < BOOK_BUF) |
1187 | { |
1183 | { |
1188 | /* monster description */ |
1184 | /* monster description */ |
… | |
… | |
1256 | buf.printf ("Herein %s detailed %s...\n", |
1252 | buf.printf ("Herein %s detailed %s...\n", |
1257 | book_entries > 1 ? "are" : "is", |
1253 | book_entries > 1 ? "are" : "is", |
1258 | book_entries > 1 ? "some artifacts" : "an artifact"); |
1254 | book_entries > 1 ? "some artifacts" : "an artifact"); |
1259 | |
1255 | |
1260 | /* artifact msg attributes loop. Lets keep adding entries to the 'book' |
1256 | /* artifact msg attributes loop. Lets keep adding entries to the 'book' |
1261 | * as long as we have space up to the allowed max # (book_entires) |
1257 | * as long as we have space up to the allowed max # (book_entires) |
1262 | */ |
1258 | */ |
1263 | while (book_entries > 0 && buf.size () < BOOK_BUF) |
1259 | while (book_entries > 0 && buf.size () < BOOK_BUF) |
1264 | { |
1260 | { |
1265 | |
1261 | |
1266 | if (!art) |
1262 | if (!art) |
… | |
… | |
1327 | /***************************************************************************** |
1323 | /***************************************************************************** |
1328 | * Spellpath message generation |
1324 | * Spellpath message generation |
1329 | *****************************************************************************/ |
1325 | *****************************************************************************/ |
1330 | |
1326 | |
1331 | /* spellpath_msg() - generate a message detailing the member |
1327 | /* spellpath_msg() - generate a message detailing the member |
1332 | * incantations/prayers (and some of their properties) belonging to |
1328 | * incantations/prayers (and some of their properties) belonging to |
1333 | * a given spellpath. |
1329 | * a given spellpath. |
1334 | */ |
1330 | */ |
1335 | static char * |
1331 | static char * |
1336 | spellpath_msg (int level) |
1332 | spellpath_msg (int level) |
1337 | { |
1333 | { |
1338 | static dynbuf_text buf; buf.clear (); |
1334 | static dynbuf_text buf; buf.clear (); |
… | |
… | |
1386 | int chance; |
1382 | int chance; |
1387 | |
1383 | |
1388 | static dynbuf_text buf; buf.clear (); |
1384 | static dynbuf_text buf; buf.clear (); |
1389 | |
1385 | |
1390 | /* the higher the book level, the more complex (ie number of |
1386 | /* the higher the book level, the more complex (ie number of |
1391 | * ingredients) the formula can be. |
1387 | * ingredients) the formula can be. |
1392 | */ |
1388 | */ |
1393 | fl = get_formulalist (rndm (level) / 3 + 1); |
1389 | fl = get_formulalist (rndm (level) / 3 + 1); |
1394 | |
1390 | |
1395 | if (!fl) |
1391 | if (!fl) |
1396 | fl = get_formulalist (1); /* safety */ |
1392 | fl = get_formulalist (1); /* safety */ |
… | |
… | |
1676 | buf << "[Unfortunately the rest of the information is hopelessly garbled!]"; |
1672 | buf << "[Unfortunately the rest of the information is hopelessly garbled!]"; |
1677 | |
1673 | |
1678 | return buf; |
1674 | return buf; |
1679 | } |
1675 | } |
1680 | |
1676 | |
1681 | /* tailor_readable_ob()- The main routine. This chooses a random |
1677 | /* tailor_readable_ob()- The main routine. This chooses a random |
1682 | * message to put in given readable object (type==BOOK) which will |
1678 | * message to put in given readable object (type==BOOK) which will |
1683 | * be referred hereafter as a 'book'. We use the book level to de- |
1679 | * be referred hereafter as a 'book'. We use the book level to de- |
1684 | * termine the value of the information we will insert. Higher |
1680 | * termine the value of the information we will insert. Higher |
1685 | * values mean the book will (generally) have better/more info. |
1681 | * values mean the book will (generally) have better/more info. |
1686 | * See individual cases as to how this will be utilized. |
1682 | * See individual cases as to how this will be utilized. |
1687 | * "Book" name/content length are based on the weight of the |
1683 | * "Book" name/content length are based on the weight of the |
1688 | * document. If the value of msg_type is negative, we will randomly |
1684 | * document. If the value of msg_type is negative, we will randomly |
1689 | * choose the kind of message to generate. |
1685 | * choose the kind of message to generate. |
1690 | * -b.t. thomas@astro.psu.edu |
1686 | * -b.t. thomas@astro.psu.edu |
1691 | * |
1687 | * |
1692 | * book is the object we are creating into. |
1688 | * book is the object we are creating into. |
1693 | * If msg_type is a positive value, we use that to determine the |
1689 | * If msg_type is a positive value, we use that to determine the |
1694 | * message type - otherwise a random value is used. |
1690 | * message type - otherwise a random value is used. |