From cbef37bd5bfb938a2303ee3887520c08be85d8e8 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 17:10:10 +0100 Subject: Switch almost everything over to C++ --- src/messages.cc | 365 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 src/messages.cc (limited to 'src/messages.cc') diff --git a/src/messages.cc b/src/messages.cc new file mode 100644 index 00000000..32117198 --- /dev/null +++ b/src/messages.cc @@ -0,0 +1,365 @@ +#include "messages.h" +#include "tome/make_array.hpp" + +#include "angband.h" + +/* + * OPTION: Maximum number of messages to remember (see "io.c") + * Default: assume maximal memorization of 2048 total messages + */ +#define MESSAGE_MAX 2048 + +/* + * OPTION: Maximum space for the message text buffer (see "io.c") + * Default: assume that each of the 2048 messages is repeated an + * average of three times, and has an average length of 48 + */ +#define MESSAGE_BUF 32768 + + + + +/* + * The next "free" index to use + */ +static u16b message__next; + +/* + * The index of the oldest message (none yet) + */ +static u16b message__last; + +/* + * The next "free" offset + */ +static u16b message__head; + +/* + * The offset to the oldest used char (none yet) + */ +static u16b message__tail; + +/* + * The array of offsets, by index [MESSAGE_MAX] + */ +static u16b *message__ptr; + +/* + * The array of colors, by index [MESSAGE_MAX] + */ +static byte *message__color; + +/* + * The array of message counts, by index [MESSAGE_MAX] + */ +static u16b *message__count; + +/* + * The array of chars, by offset [MESSAGE_BUF] + */ +static char *message__buf; + + +/* +* Second try for the "message" handling routines. +* +* Each call to "message_add(s)" will add a new "most recent" message +* to the "message recall list", using the contents of the string "s". +* +* The messages will be stored in such a way as to maximize "efficiency", +* that is, we attempt to maximize the number of sequential messages that +* can be retrieved, given a limited amount of storage space. +* +* We keep a buffer of chars to hold the "text" of the messages, not +* necessarily in "order", and an array of offsets into that buffer, +* representing the actual messages. This is made more complicated +* by the fact that both the array of indexes, and the buffer itself, +* are both treated as "circular arrays" for efficiency purposes, but +* the strings may not be "broken" across the ends of the array. +* +* The "message_add()" function is rather "complex", because it must be +* extremely efficient, both in space and time, for use with the Borg. +*/ + +void message_init() +{ + /* Message variables */ + message__ptr = make_array(MESSAGE_MAX); + message__color = make_array(MESSAGE_MAX); + message__count = make_array(MESSAGE_MAX); + message__buf = make_array(MESSAGE_BUF); + + /* Hack -- No messages yet */ + message__tail = MESSAGE_BUF; +} + +/* +* How many messages are "available"? +*/ +s16b message_num(void) +{ + int last, next, n; + + /* Extract the indexes */ + last = message__last; + next = message__next; + + /* Handle "wrap" */ + if (next < last) next += MESSAGE_MAX; + + /* Extract the space */ + n = (next - last); + + /* Return the result */ + return (n); +} + + + +/* +* Recall the "text" of a saved message +*/ +cptr message_str(int age) +{ + static char buf[1024]; + s16b x; + s16b o; + cptr s; + + /* Forgotten messages have no text */ + if ((age < 0) || (age >= message_num())) return (""); + + /* Acquire the "logical" index */ + x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX; + + /* Get the "offset" for the message */ + o = message__ptr[x]; + + /* Access the message text */ + s = &message__buf[o]; + + /* Hack -- Handle repeated messages */ + if (message__count[x] > 1) + { + strnfmt(buf, 1024, "%s <%dx>", s, message__count[x]); + s = buf; + } + + /* Return the message text */ + return (s); +} + +/* +* Recall the color of a saved message +*/ +byte message_color(int age) +{ + s16b x; + byte color = TERM_WHITE; + + /* Forgotten messages have no text */ + if ((age < 0) || (age >= message_num())) return (TERM_WHITE); + + /* Acquire the "logical" index */ + x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX; + + /* Get the "offset" for the message */ + color = message__color[x]; + + /* Return the message text */ + return (color); +} + + +/* +* Add a new message, with great efficiency +*/ +void message_add(cptr str, byte color) +{ + int i, k, x, n; + cptr s; + + + /*** Step 1 -- Analyze the message ***/ + + /* Hack -- Ignore "non-messages" */ + if (!str) return; + + /* Message length */ + n = strlen(str); + + /* Important Hack -- Ignore "long" messages */ + if (n >= MESSAGE_BUF / 4) return; + + + /*** Step 2 -- Handle repeated messages ***/ + + /* Acquire the "logical" last index */ + x = (message__next + MESSAGE_MAX - 1) % MESSAGE_MAX; + + /* Get the last message text */ + s = &message__buf[message__ptr[x]]; + + /* Last message repeated? */ + if (streq(str, s)) + { + /* Increase the message count */ + message__count[x]++; + + /* Success */ + return; + } + + + /*** Step 3 -- Attempt to optimize ***/ + + /* Limit number of messages to check */ + k = message_num() / 4; + + /* Limit number of messages to check */ + if (k > MESSAGE_MAX / 32) k = MESSAGE_MAX / 32; + + /* Check the last few messages (if any to count) */ + for (i = message__next; k; k--) + { + u16b q; + + cptr old; + + /* Back up and wrap if needed */ + if (i-- == 0) i = MESSAGE_MAX - 1; + + /* Stop before oldest message */ + if (i == message__last) break; + + /* Extract "distance" from "head" */ + q = (message__head + MESSAGE_BUF - message__ptr[i]) % MESSAGE_BUF; + + /* Do not optimize over large distance */ + if (q > MESSAGE_BUF / 2) continue; + + /* Access the old string */ + old = &message__buf[message__ptr[i]]; + + /* Compare */ + if (!streq(old, str)) continue; + + /* Get the next message index, advance */ + x = message__next++; + + /* Handle wrap */ + if (message__next == MESSAGE_MAX) message__next = 0; + + /* Kill last message if needed */ + if (message__next == message__last) message__last++; + + /* Handle wrap */ + if (message__last == MESSAGE_MAX) message__last = 0; + + /* Assign the starting address */ + message__ptr[x] = message__ptr[i]; + message__color[x] = color; + message__count[x] = 1; + + /* Success */ + return; + } + + + /*** Step 4 -- Ensure space before end of buffer ***/ + + /* Kill messages and Wrap if needed */ + if (message__head + n + 1 >= MESSAGE_BUF) + { + /* Kill all "dead" messages */ + for (i = message__last; TRUE; i++) + { + /* Wrap if needed */ + if (i == MESSAGE_MAX) i = 0; + + /* Stop before the new message */ + if (i == message__next) break; + + /* Kill "dead" messages */ + if (message__ptr[i] >= message__head) + { + /* Track oldest message */ + message__last = i + 1; + } + } + + /* Wrap "tail" if needed */ + if (message__tail >= message__head) message__tail = 0; + + /* Start over */ + message__head = 0; + } + + + /*** Step 5 -- Ensure space before next message ***/ + + /* Kill messages if needed */ + if (message__head + n + 1 > message__tail) + { + /* Grab new "tail" */ + message__tail = message__head + n + 1; + + /* Advance tail while possible past first "nul" */ + while (message__buf[message__tail - 1]) message__tail++; + + /* Kill all "dead" messages */ + for (i = message__last; TRUE; i++) + { + /* Wrap if needed */ + if (i == MESSAGE_MAX) i = 0; + + /* Stop before the new message */ + if (i == message__next) break; + + /* Kill "dead" messages */ + if ((message__ptr[i] >= message__head) && + (message__ptr[i] < message__tail)) + { + /* Track oldest message */ + message__last = i + 1; + } + } + } + + + /*** Step 6 -- Grab a new message index ***/ + + /* Get the next message index, advance */ + x = message__next++; + + /* Handle wrap */ + if (message__next == MESSAGE_MAX) message__next = 0; + + /* Kill last message if needed */ + if (message__next == message__last) message__last++; + + /* Handle wrap */ + if (message__last == MESSAGE_MAX) message__last = 0; + + + + /*** Step 7 -- Insert the message text ***/ + + /* Assign the starting address */ + message__ptr[x] = message__head; + message__color[x] = color; + message__count[x] = 1; + + /* Append the new part of the message */ + for (i = 0; i < n; i++) + { + /* Copy the message */ + message__buf[message__head + i] = str[i]; + } + + /* Terminate */ + message__buf[message__head + i] = '\0'; + + /* Advance the "head" pointer */ + message__head += n + 1; +} -- cgit v1.2.3