From bc1869c1a3334676d5cc99df90f7f9b24426274d Mon Sep 17 00:00:00 2001 From: j-p-e-g Date: Tue, 20 Mar 2007 12:12:03 +0000 Subject: Added a funtion for formatted message history, and, while I was at it, moved some overlapping parts of base_mpr and formatted_mpr into separate functions. This makes them more readable and avoids code duplication. I'm uncertain as to whether translating every string in replay_messages into a formatted string (just in case) would be overkill - so for now that only happens for messages of MSGCH_TUTORIAL. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1071 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/acr.cc | 4 +- crawl-ref/source/menu.cc | 28 ++--- crawl-ref/source/message.cc | 244 ++++++++++++++++++++++--------------------- crawl-ref/source/message.h | 5 +- crawl-ref/source/output.cc | 4 +- crawl-ref/source/tutorial.cc | 140 ++++++++++++++++++------- 6 files changed, 252 insertions(+), 173 deletions(-) (limited to 'crawl-ref') diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 7c45aa60a3..1766076e1f 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -221,8 +221,8 @@ int main( int argc, char *argv[] ) bool game_start = initialise(); - // override some options for tutorial - init_tutorial_options(); + // override some options for tutorial + init_tutorial_options(); if (game_start || Options.always_greet) { diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index bc7ee61821..35e054f0d9 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -1180,13 +1180,13 @@ int linebreak_string2( std::string& s, int maxcol ) // hard linebreak else if ( xpos >= maxcol ) { - if (spacepos >= xpos-maxcol) + if (spacepos >= xpos-maxcol) { - loc = spacepos; - s.replace(loc, 1, "\n"); - } - else - s.insert(loc, "\n"); + loc = spacepos; + s.replace(loc, 1, "\n"); + } + else + s.insert(loc, "\n"); xpos = 0; ++breakcount; } @@ -1212,19 +1212,21 @@ void print_formatted_paragraph(std::string &s, int maxcol, int channel) { linebreak_string2(s,maxcol); std::string text; - + size_t loc = 0, oldloc = 0; while ( loc < s.size() ) { if (s[loc] == '\n') { - text = s.substr(oldloc, loc-oldloc); - formatted_mpr( formatted_string::parse_string(text), channel ); - oldloc = ++loc; - } + text = s.substr(oldloc, loc-oldloc); +// formatted_mpr( formatted_string::parse_string(text), channel ); + formatted_message_history( text, channel ); + oldloc = ++loc; + } loc++; } - formatted_mpr( formatted_string::parse_string( s.substr(oldloc, loc-oldloc) ), channel ); -} +// formatted_mpr( formatted_string::parse_string( s.substr(oldloc, loc-oldloc) ), channel ); + formatted_message_history( s.substr(oldloc, loc-oldloc), channel ); +} bool formatted_scroller::jump_to( int i ) { diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index 4bad0ce3d1..d1b1a45ff8 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -308,34 +308,25 @@ void mpr(const char *inf, int channel, int param) } } -static bool need_prefix = false; -static void base_mpr(const char *inf, int channel, int param) +// checks whether a given message contains patterns relevant for +// notes, stop_running or sounds and handles these cases +static void mpr_check_patterns(std::string message, int channel, int param) { - if (suppress_messages) - return; - - int colour = channel_to_colour( channel, param ); - if (colour == MSGCOL_MUTED) - return; - - std::string imsg = inf; - for (unsigned i = 0; i < Options.note_messages.size(); ++i) { - if (Options.note_messages[i].matches(imsg)) + if (Options.note_messages[i].matches(message)) { - take_note(Note(NOTE_MESSAGE, channel, param, inf)); + take_note(Note( NOTE_MESSAGE, channel, param, message.c_str() )); break; } } if (channel != MSGCH_DIAGNOSTICS && channel != MSGCH_EQUIPMENT) - interrupt_activity( AI_MESSAGE, channel_to_str(channel) + ":" + inf ); + interrupt_activity( AI_MESSAGE, channel_to_str(channel) + ":" + message ); // Check messages for all forms of running now. if (you.running) { - std::string message = inf; for (unsigned i = 0; i < Options.travel_stop_message.size(); ++i) { if (Options.travel_stop_message[i].is_filtered( channel, message )) @@ -346,12 +337,11 @@ static void base_mpr(const char *inf, int channel, int param) } } - if (!Options.sound_mappings.empty()) + if (!Options.sound_mappings.empty()) { - std::string message = inf; - for (unsigned i = 0; i < Options.sound_mappings.size(); i++) + for (unsigned i = 0; i < Options.sound_mappings.size(); i++) { - // Maybe we should allow message channel matching as for + // Maybe we should allow message channel matching as for // travel_stop_message? if (Options.sound_mappings[i].pattern.matches(message)) { @@ -361,44 +351,19 @@ static void base_mpr(const char *inf, int channel, int param) } } - if (!Options.message_colour_mappings.empty()) - { - std::string message = inf; - for (int i = 0, size = Options.message_colour_mappings.size(); - i < size; ++i) - { - const message_colour_mapping &m = - Options.message_colour_mappings[i]; - if (m.message.is_filtered(channel, message)) - { - colour = m.colour; - break; - } - } - } - - flush_input_buffer( FLUSH_ON_MESSAGE ); +} +// adds a given message to the message history +static void mpr_store_messages(std::string message, int channel, int param) +{ const int num_lines = get_message_window_height(); - - if (New_Message_Count == num_lines - 1) - more(); - - if (need_prefix) - { - message_out( Message_Line, colour, "-", 1, false ); - need_prefix = false; - } - - message_out( Message_Line, colour, inf, - Options.delay_message_clear? 2 : 1 ); // Prompt lines are presumably shown to / seen by the player accompanied // by a request for input, which should do the equivalent of a more(); to // save annoyance, don't bump New_Message_Count for prompts. if (channel != MSGCH_PROMPT) New_Message_Count++; - + if (Message_Line < num_lines - 1) Message_Line++; @@ -409,7 +374,7 @@ static void base_mpr(const char *inf, int channel, int param) if (channel != MSGCH_EQUIPMENT) { // Put the message into Store_Message, and move the '---' line forward - Store_Message[ Next_Message ].text = inf; + Store_Message[ Next_Message ].text = message.c_str(); Store_Message[ Next_Message ].channel = channel; Store_Message[ Next_Message ].param = param; Next_Message++; @@ -417,15 +382,10 @@ static void base_mpr(const char *inf, int channel, int param) if (Next_Message >= NUM_STORED_MESSAGES) Next_Message = 0; } -} // end mpr() - +} -// Line wrapping is not available here! -// Note that the colour will be first set to the appropriate channel -// colour before displaying the formatted_string. -// XXX This code just reproduces base_mpr(). There must be a better -// way to do this. -void formatted_mpr(const formatted_string& fs, int channel, int param) +static bool need_prefix = false; +static void base_mpr(const char *inf, int channel, int param) { if (suppress_messages) return; @@ -434,42 +394,21 @@ void formatted_mpr(const formatted_string& fs, int channel, int param) if (colour == MSGCOL_MUTED) return; - const std::string imsg = fs.tostring(); + std::string imsg = inf; - for (unsigned i = 0; i < Options.note_messages.size(); ++i) - { - if (Options.note_messages[i].matches(imsg)) - { - take_note(Note(NOTE_MESSAGE, channel, param, imsg.c_str())); - break; - } - } - - if (channel != MSGCH_DIAGNOSTICS && channel != MSGCH_EQUIPMENT) - interrupt_activity(AI_MESSAGE, channel_to_str(channel) + ":" + imsg); - - // Check messages for all forms of running now. - if (you.running) - { - for (unsigned i = 0; i < Options.travel_stop_message.size(); ++i) - { - if (Options.travel_stop_message[i].is_filtered(channel, imsg)) - { - stop_running(); - break; - } - } - } - - if (Options.sound_mappings.size() > 0) + mpr_check_patterns(imsg, channel, param); + + if (!Options.message_colour_mappings.empty()) { - for (unsigned i = 0; i < Options.sound_mappings.size(); i++) + std::string message = inf; + for (int i = 0, size = Options.message_colour_mappings.size(); + i < size; ++i) { - // Maybe we should allow message channel matching as for - // travel_stop_message? - if (Options.sound_mappings[i].pattern.matches(imsg)) + const message_colour_mapping &m = + Options.message_colour_mappings[i]; + if (m.message.is_filtered(channel, message)) { - play_sound(Options.sound_mappings[i].soundfile.c_str()); + colour = m.colour; break; } } @@ -482,6 +421,21 @@ void formatted_mpr(const formatted_string& fs, int channel, int param) if (New_Message_Count == num_lines - 1) more(); + if (need_prefix) + { + message_out( Message_Line, colour, "-", 1, false ); + need_prefix = false; + } + + message_out( Message_Line, colour, inf, + Options.delay_message_clear? 2 : 1 ); + + mpr_store_messages(imsg, channel, param); +} // end mpr() + + +static void mpr_formatted_output(formatted_string fs, int colour) +{ int curcol = 1; if (need_prefix) @@ -509,33 +463,65 @@ void formatted_mpr(const formatted_string& fs, int channel, int param) } } message_out( Message_Line, colour, "", Options.delay_message_clear? 2 : 1); +} - // Prompt lines are presumably shown to / seen by the player accompanied - // by a request for input, which should do the equivalent of a more(); to - // save annoyance, don't bump New_Message_Count for prompts. - if (channel != MSGCH_PROMPT) - New_Message_Count++; +// Line wrapping is not available here! +// Note that the colour will be first set to the appropriate channel +// colour before displaying the formatted_string. +// XXX This code just reproduces base_mpr(). There must be a better +// way to do this. +void formatted_mpr(const formatted_string& fs, int channel, int param) +{ + if (suppress_messages) + return; + + int colour = channel_to_colour( channel, param ); + if (colour == MSGCOL_MUTED) + return; + + const std::string imsg = fs.tostring(); - if (Message_Line < num_lines - 1) - Message_Line++; + mpr_check_patterns(imsg, channel, param); - // reset colour - textcolor(LIGHTGREY); + flush_input_buffer( FLUSH_ON_MESSAGE ); - // equipment lists just waste space in the message recall - if (channel != MSGCH_EQUIPMENT) - { - // Put the message into Store_Message, and move the '---' line forward - Store_Message[ Next_Message ].text = imsg.c_str(); - Store_Message[ Next_Message ].channel = channel; - Store_Message[ Next_Message ].param = param; - Next_Message++; + const int num_lines = get_message_window_height(); + + if (New_Message_Count == num_lines - 1) + more(); + + mpr_formatted_output(fs, colour); - if (Next_Message >= NUM_STORED_MESSAGES) - Next_Message = 0; - } + mpr_store_messages(imsg, channel, param); } +// output given string as formatted message, but check patterns +// for string stripped of tags and store original tagged string +// for message history +void formatted_message_history(const std::string st, int channel, int param) +{ + if (suppress_messages) + return; + + int colour = channel_to_colour( channel, param ); + if (colour == MSGCOL_MUTED) + return; + + formatted_string fs = formatted_string::parse_string(st); + + mpr_check_patterns(fs.tostring(), channel, param); + + flush_input_buffer( FLUSH_ON_MESSAGE ); + + const int num_lines = get_message_window_height(); + + if (New_Message_Count == num_lines - 1) + more(); + + mpr_formatted_output(fs, colour); + + mpr_store_messages(st, channel, param); +} bool any_messages(void) { @@ -676,18 +662,36 @@ void replay_messages(void) textcolor( colour ); + std::string text = Store_Message[ line ].text; + // for tutorial texts (for now, used for debugging) + // allow formatted output of tagged messages + if (Store_Message[ line ].channel == MSGCH_TUTORIAL) + { + formatted_string fs = formatted_string::parse_string(text); + int curcol = 1; + for ( unsigned int j = 0; j < fs.ops.size(); ++j ) + { + switch ( fs.ops[j].type ) + { + case FSOP_COLOUR: + colour = fs.ops[j].x; + break; + case FSOP_TEXT: + textcolor( colour ); + gotoxy(curcol, wherey()); + cprintf(fs.ops[j].text.c_str()); + curcol += fs.ops[j].text.length(); + break; + case FSOP_CURSOR: + break; + } + } + } + else #if DEBUG_DIAGNOSTICS - cprintf( "%d: %s", line, Store_Message[ line ].text.c_str() ); + cprintf( "%d: %s", line, text.c_str() ); #else - /* TODO: allow colour changes in previous messages, as well - if (Store_Message[ line ].channel == MSGCH_TUTORIAL) - { - formatted_string help = formatted_string::parse_string(Store_Message[ line ].text); - help.display(); - } - else - */ - cprintf( "%s", Store_Message[ line ].text.c_str() ); + cprintf( "%s", text.c_str() ); #endif cprintf(EOL); diff --git a/crawl-ref/source/message.h b/crawl-ref/source/message.h index ec6e4258af..0d82a195d3 100644 --- a/crawl-ref/source/message.h +++ b/crawl-ref/source/message.h @@ -59,7 +59,10 @@ class formatted_string; void formatted_mpr(const formatted_string& fs, int channel = MSGCH_PLAIN, int param = 0); - + +void formatted_message_history(const std::string st, + int channel = MSGCH_PLAIN, int param = 0); + // 4.1-style mpr, currently named mprf for minimal disruption. void mprf( int channel, const char *format, ... ); void mprf( const char *format, ... ); diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index 2d952b5919..5789c3f879 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -973,7 +973,7 @@ void print_overview_screen() bool calc_unid = false; formatted_scroller cmd_help; // Set flags, and don't use easy exit. - cmd_help.set_flags(MF_NOSELECT | MF_NOWRAP, false); + cmd_help.set_flags(MF_NOSELECT | MF_ALWAYS_SHOW_MORE | MF_NOWRAP, false); cmd_help.set_more( formatted_string::parse_string( "[ + : Page down. - : Page up. Esc exits.]")); @@ -1563,8 +1563,8 @@ std::string status_mut_abilities() text += ", able to fly"; if (you.experience_level > 14) text += " continuously"; - have_any = true; } + have_any = true; break; case SP_MUMMY: diff --git a/crawl-ref/source/tutorial.cc b/crawl-ref/source/tutorial.cc index 6cbe6f8a47..3c3b04cbc2 100644 --- a/crawl-ref/source/tutorial.cc +++ b/crawl-ref/source/tutorial.cc @@ -22,7 +22,7 @@ //#define TUTORIAL_DEBUG #define TUTORIAL_VERSION 110 -int COLS = get_number_of_cols(); +int COLS = (get_number_of_cols() > 80) ? 80 : get_number_of_cols(); void save_tutorial( FILE* fp ) { @@ -226,7 +226,7 @@ static formatted_string tut_starting_info(unsigned int width) linebreak_string2(text, width); result += formatted_string::parse_string(text); - result += "For the moment, just remember the following two keys and their functions:" EOL; + result += "For the moment, just remember the following keys and their functions:" EOL; result += " ? - shows the items and the commands" EOL; result += " S - saves the game, to be resumed later (but note that death is permanent)" EOL; result += " x - examine something in your vicinity" EOL EOL; @@ -257,7 +257,7 @@ static std::string tut_debug_list(int event) case TUT_SEEN_FIRST_OBJECT: return "seen first object"; case TUT_SEEN_POTION: - return "seen first potion"; + return "seen first potion"; case TUT_SEEN_SCROLL: return "seen first scroll"; case TUT_SEEN_WAND: @@ -781,23 +781,84 @@ void taken_new_item(unsigned char item_type) } } +static std::string colour_to_tag(int col, bool closed = false) +{ + std::string tag = "<"; + if (closed) + tag += "/"; + switch(col) + { + case WHITE: + tag += "w"; + break; + case YELLOW: + tag += "yellow"; + break; + case RED: + tag += "red"; + break; + case LIGHTRED: + tag += "lightred"; + break; + case MAGENTA: + tag += "magenta"; + break; + case LIGHTMAGENTA: + tag += "lightmagenta"; + break; + case GREEN: + tag += "green"; + break; + case LIGHTGREEN: + tag += "lightgreen"; + break; + case BLUE: + tag += "blue"; + break; + case LIGHTBLUE: + tag += "lightblue"; + break; + case CYAN: + tag += "cyan"; + break; + case LIGHTCYAN: + tag += "lightcyan"; + break; + case BLACK: + tag += "black"; + break; + case BROWN: + tag += "brown"; + break; + case DARKGREY: + tag += "darkgrey"; + break; + default: + tag += "lightgrey"; + } + tag += ">"; + + return tag; + +} + void tutorial_first_monster(monsters mon) { if (!Options.tutorial_events[TUT_SEEN_MONSTER]) return; + unsigned short ch, col; + get_mons_glyph(&mon, &ch, &col); + std::string text = "That "; - formatted_string st = formatted_string::parse_string(text); - st.formatted_string::textcolor(channel_to_colour(MSGCH_TUTORIAL)); - st.formatted_string::add_glyph(&mon); - text = " is a monster, usually depicted by a letter. Some typical early monsters "; - st += formatted_string::parse_string(text); - formatted_mpr(st, MSGCH_TUTORIAL); - - text = "look like r, g, b or " - "K. You can gain information about it by pressing " - "x, moving the cursor on the monster and then pressing " - "v. To attack it with your wielded weapon, just move into it."; + text += colour_to_tag(col); + text += ch; + text += " is a monster, usually depicted by a letter. Some typical " + "early monsters look like r, g, " + "b or K. You can gain " + "information about it by pressing x, moving the cursor " + "on the monster and then pressing v. To attack it with " + "your wielded weapon, just move into it."; print_formatted_paragraph(text, COLS, MSGCH_TUTORIAL); more(); @@ -836,19 +897,17 @@ void tutorial_first_item(item_def item) if (!Options.tutorial_events[TUT_SEEN_FIRST_OBJECT] || Options.tut_just_triggered) return; + unsigned short ch, col; + get_item_glyph(&item, &ch, &col); + std::string text = "That "; - formatted_string st = formatted_string::parse_string(text); - st.formatted_string::textcolor(channel_to_colour(MSGCH_TUTORIAL)); - st.formatted_string::add_glyph(&item); - text = " is an item. If you move there and press g or " - ", you will pick it up."; - st += formatted_string::parse_string(text); - formatted_mpr(st, MSGCH_TUTORIAL); - - text = "Generally, items are shown by non-letter symbols like " - "%%?!\"=()[. Once it is in your inventory, you can drop " - "it again with d. Several types of objects will usually " - "be picked up automatically."; + text += colour_to_tag(col); + text += ch; + text += " is an item. If you move there and press g or " + ", you will pick it up. Generally, items are shown by " + "non-letter symbols like %%?!\"=()[. Once it is in your " + "inventory, you can drop it again with d. Several types " + "of objects will usually be picked up automatically."; print_formatted_paragraph(text, COLS, MSGCH_TUTORIAL); Options.tutorial_events[TUT_SEEN_FIRST_OBJECT] = 0; @@ -869,6 +928,9 @@ void learned_something_new(unsigned int seen_what, int x, int y) std::string text; unsigned short ch, colour; + const int ex = x - you.x_pos + 9; + const int ey = y - you.y_pos + 9; + int object; switch(seen_what) { @@ -886,9 +948,8 @@ void learned_something_new(unsigned int seen_what, int x, int y) break; case TUT_SEEN_SPBOOK: get_item_symbol(DNGN_ITEM_BOOK, &ch, &colour); - snprintf(info, INFO_SIZE, "%c", ch); text = "You have picked up a spellbook ('"; - text += info; + text += ch; text += "'). You can read it by typing r, " "memorise spells via M and cast a memorised spell " "with Z."; @@ -982,10 +1043,9 @@ void learned_something_new(unsigned int seen_what, int x, int y) break; case TUT_SEEN_STAFF: get_item_symbol(DNGN_ITEM_STAVE, &ch, &colour); - snprintf(info, INFO_SIZE, "%c", ch); text = "You have picked up a magic staff or a rod, both of which are " "represented by '"; - text += info; + text += ch; text += "'. Both must be ielded to be of use. " "Magicians use staves to increase their power in certain spell " "schools. By contrast, a rod allows the casting of certain " @@ -997,8 +1057,13 @@ void learned_something_new(unsigned int seen_what, int x, int y) if (you.num_turns < 1) return; + object = env.show[ex][ey]; + colour = env.show_col[ex][ey]; + get_item_symbol( object, &ch, &colour ); + text = "The "; - text += get_screen_glyph(x,y); + text += colour_to_tag(colour); + text += ch; text += " are some downstairs. You can enter the next (deeper) " "level by following them down (>). To get back to " "this level again, press << while standing on the " @@ -1013,8 +1078,13 @@ void learned_something_new(unsigned int seen_what, int x, int y) "effects, like teleportation."; break; case TUT_SEEN_ALTAR: - text = "The "; - text += get_screen_glyph(x,y); + object = env.show[ex][ey]; + colour = env.show_col[ex][ey]; + get_item_symbol( object, &ch, &colour ); + + text = "The "; + text += colour_to_tag(colour); + text += ch; text += " is an altar. You can get information about it by pressing " "p while standing on the square. Before taking up " "the responding faith you'll be asked for confirmation."; @@ -1103,7 +1173,7 @@ void learned_something_new(unsigned int seen_what, int x, int y) text = "There are two ways to overcome hunger: food you started " "with or found, and selfmade chunks from corpses. To get the " "latter, all you need to do is D a corpse with a " - "sharp implement. Your starting weapon will do nicely." + "sharp implement. Your starting weapon will do nicely. " "Try to dine on chunks in order to save permanent food."; break; case TUT_YOU_STARVING: @@ -1217,7 +1287,7 @@ void learned_something_new(unsigned int seen_what, int x, int y) "danger of dying, check your options carefully. Often, retreat or " "use of some item might be a viable alternative to fighting on."; if (you.species == SP_CENTAUR) - text += "As a four-legged centaur you are particularly quick - " + text += " As a four-legged centaur you are particularly quick - " "running is an option! "; if (Options.tutorial_type == TUT_BERSERK_CHAR && !you.berserker) { -- cgit v1.2.3-54-g00ecf