#include <mail.h> #include <board.h>; inherit "/std/object"; string board_name; mapping being_written; int action_pri; class info_written { string subject; int note_num; } int do_read_next(); int do_read_new(); int do_read(int num); int do_followup(int num); int do_reply(int num); int do_eat(int num); int do_post(string str); void setup() { set_name("board"); set_short("bulletin board"); add_adjective("bulletin"); set_main_plural("boards"); reset_get(); add_property("there", "mounted on one wall"); add_property("survive fire", 1); add_help_file("board"); board_name = "frog"; being_written = ([ ]); action_pri = 0; } /* setup() */ string query_plural() { mixed *stuff; stuff = (mixed *)BOARD_HAND->get_subjects(board_name); switch (sizeof(stuff)) { case 0: return pluralize(::short(0))+" [ Empty ]"; case 1: return pluralize(::short(0))+" [ 1 note ]"; } return pluralize(::short(0))+" [ "+sizeof(stuff)+" notes ]"; } /* query_plural() */ string short(int dark) { mixed *stuff; stuff = (mixed *)BOARD_HAND->get_subjects(board_name); switch (sizeof(stuff)) { case 0: return ::short(dark)+" [ Empty ]"; case 1: return ::short(dark)+" [ 1 note ]"; default: return ::short(dark)+" [ "+sizeof(stuff)+" notes ]"; } } /* short() */ string the_date(int i) { return ctime(i)[4..9]; } /* the_date() */ int do_subjects(string search) { int i, size; mixed *stuff; string ret; mapping news_rc; search = lower_case(search); stuff = (mixed *)BOARD_HAND->get_subjects(board_name); if (!sizeof(stuff)) { add_failed_mess("The board is completely empty.\n"); return 0; } news_rc = BOARD_HAND->query_newsrc(this_player()->query_name()); if (!news_rc) { news_rc = ([ ]); } ret = ""; size = sizeof(stuff); for (i=0; i < size; i++) { if(search != "" && strsrch(lower_case(stuff[i][B_SUBJECT]), search) == -1) continue; if (news_rc[board_name] < stuff[i][B_TIME]) { ret += sprintf("N %2d: %-=*s\n", i+1, (int)this_player()->query_cols()-6, stuff[i][B_SUBJECT]+" ("+ stuff[i][B_NAME]+" "+the_date(stuff[i][B_TIME])+")"); } else { ret += sprintf(" %2d: %-=*s\n", i+1, (int)this_player()->query_cols()-6, stuff[i][B_SUBJECT]+" ("+ stuff[i][B_NAME]+" "+the_date(stuff[i][B_TIME])+")"); } } this_player()->set_finish_func(0); this_player()->more_string(ret); return 1; } /* subjects() */ string long(string str, int dark) { int i,newones, size; mixed *stuff; string ret; mapping news_rc; stuff = (mixed *)BOARD_HAND->get_subjects(board_name); ret = "A bulletin board ("+board_name+").\n"; /* ret += sprintf("%#-*s\n\n", this_player()->query_cols(), "read [note number]\nsubjects\n"+ (this_player()->query_property("guest")?"": "post <subject>\neat <note number>\n"+ "reply <note number>\nfollowup <note number>\n")); */ if (!sizeof(stuff)) { return ret+"The board is completely empty.\n"; } news_rc = BOARD_HAND->query_newsrc(this_player()->query_name()); if (!news_rc) { news_rc = ([ ]); } newones = 0; size = sizeof(stuff); for (i = 0; i < size; i++) { if (news_rc[board_name] < stuff[i][B_TIME]) { ret += sprintf("N %2d: %-=*s\n", i+1, (int)this_player()->query_cols()-6, stuff[i][B_SUBJECT]+" ("+ stuff[i][B_NAME]+" "+the_date(stuff[i][B_TIME])+")"); newones +=1; } else if (news_rc[board_name] < stuff[i][B_TIME]+(2*24*60*60)) { ret += sprintf(" %2d: %-=*s\n", i+1, (int)this_player()->query_cols()-6, stuff[i][B_SUBJECT]+" ("+ stuff[i][B_NAME]+" "+the_date(stuff[i][B_TIME])+")"); } } if (!newones) { ret += "\nNo new messages\n"; } return ret; } /* long() */ void add_commands() { add_command("read", "[new]", (: do_read_new :)); add_command("r", "[new]", (: do_read_new :)); add_command("read", "<number>", (: do_read($4[0]) :)); add_command("r", "<number>", (: do_read($4[0]) :)); add_command("read", "next", (: do_read_next :)); if (!this_player()->query_property("guest")) { add_command("post", "<string'subject'>", (: do_post($4[0]) :)); add_command("note", "<string'subject'>", (: do_post($4[0]) :)); add_command("eat", "<number'message number'>", (: do_eat($4[0]) :)); add_command("followup", "<number'message number'>", (: do_followup($4[0]) :)); add_command("reply", "<number'message number'>", (: do_reply($4[0]) :)); } add_command("subjects", "", (: do_subjects("") :)); add_command("subjects", "<string'search'>", (: do_subjects($4[0]) :)); } /* add_commands() */ void init() { if (!present("board master", this_player())) { add_commands(); } } /* init() */ void mark_mine(mixed *stuff, mapping news_rc) { int i; string their_name; i = sizeof(stuff)-1; their_name = this_player()->query_name(); while (i > 0 && stuff[i][B_TIME] > news_rc[board_name]) i--; while ((i+1) < sizeof(stuff) && lower_case(stuff[i+1][B_NAME]) == their_name) i++; if (i >= sizeof(stuff)) { news_rc[board_name] = stuff[sizeof(stuff)-1][B_TIME]; return; } if (news_rc[board_name] > stuff[i][B_TIME]) return; news_rc[board_name] = stuff[i][B_TIME]; } /* mark_mine() */ int do_read_next() { mapping news_rc; mixed *stuff; string their_name, sub, next_sub; int num, last_time; news_rc = BOARD_HAND->query_newsrc(this_player()->query_name()); if (undefinedp(news_rc["last board"]) || news_rc["last board"] != board_name) { add_failed_mess("You have not read a note on this board yet!\n"); return 0; } stuff = BOARD_HAND->get_subjects(board_name); num = sizeof(stuff); their_name = this_player()->query_name(); write("last time: " + ctime(news_rc["last time"]) + "\n"); last_time = news_rc["last time"]; while (num && stuff[num - 1][B_TIME] > last_time) { num--; } sub = news_rc["last sub"]; sscanf(sub, "Re:#%*d %s", sub); for (++num; num <= sizeof(stuff); num++) { next_sub = stuff[num - 1][B_SUBJECT]; sscanf(next_sub, "Re:#%*d %s", next_sub); if (next_sub == sub) { return do_read(num); } } add_failed_mess("No further notes in the thread \"" + sub + "\".\n"); return 0; } /* do_read_next() */ int do_read_new() { int num; string their_name; mapping news_rc; mixed *stuff; news_rc = BOARD_HAND->query_newsrc(this_player()->query_name()); if (!news_rc) { news_rc = ([ ]); } stuff = (mixed *)BOARD_HAND->get_subjects(board_name); num = sizeof(stuff); their_name = (string)this_player()->query_name(); while(num && (stuff[num - 1][B_TIME] > news_rc[board_name])) { num--; } while ((num < sizeof(stuff)) && (lower_case(stuff[num][B_NAME]) == their_name)) { num++; } if (num == sizeof(stuff)) { add_failed_mess("No unread messages.\n"); return 0; } num++; return do_read(num); } /* do_read_new() */ int do_read(int num) { mapping news_rc; mixed *stuff; news_rc = BOARD_HAND->query_newsrc(this_player()->query_name()); if (!news_rc) { news_rc = ([ ]); } stuff = (mixed *)BOARD_HAND->get_subjects(board_name); if (num < 0) { num = sizeof(stuff) + num + 1; } if (num < 1 || (num > sizeof(stuff))) { add_failed_mess("No note of that number.\n"); return 0; } num--; news_rc["last board"] = board_name; news_rc["last time"] = stuff[num][B_TIME]; news_rc["last sub"] = stuff[num][B_SUBJECT]; if (news_rc[board_name] < stuff[num][B_TIME]) { news_rc[board_name] = stuff[num][B_TIME]; } BOARD_HAND->set_newsrc(this_player()->query_name(), news_rc); this_player()->more_string(sprintf("%s\nNote #%d by %s posted at %s%s\nTitle: " "\"%s\"\n\n%s", "%^BOLD%^", (num + 1), stuff[num][B_NAME], ctime(stuff[num][B_TIME]), "%^RESET%^", stuff[num] [B_SUBJECT][0..(int)this_player()-> query_cols() - 10], (string)BOARD_HAND-> get_message(board_name, num)), "[Note "+ (num + 1) +"]"); //add_succeeded_mess(({ "", "$N $V a note.\n" }), ({ })); add_succeeded_mess("", ({ })); return 1; } /* do_read() */ int do_post(string str) { class info_written bing; if (board_name=="announcements" && !this_player()->query_creator()) { add_failed_mess("Sorry. You can't post messages here. " "It's for announcements " "from the creators only. If you have a comment or flame, try " "the 'flame' board or the 'frog' board. Bing\n"); return 0; } if (!str) { return 0; } if (this_player()->query_sp() < BOARD_SOCIAL_POINT_COST) { add_failed_mess("You need " + BOARD_SOCIAL_POINT_COST + " social points to post a note.\n"); return 0; } /* * ok shove the editing stuff in here. Lets make it function string_edit * sound froggy? */ /* string_edit(""); body = string_edit_res; */ if (!BOARD_HAND->test_can_write(board_name, this_object(), this_player()->query_name())) { add_failed_mess("You cannot write to this board.\n"); return 0; } bing = new(class info_written); bing->subject = str; bing->note_num = 0; being_written[this_player()->query_name()] = bing; this_player()->do_edit(0, "end_of_thing"); add_succeeded_mess(({ "", "$N looks like $r is " "contemplating a note.\n" }), ({ }) ); return 1; } /* do_post() */ void end_of_thing(string body) { class info_written bing; if (body && body != "" && being_written[this_player()->query_name()]) { if(board_name != "announcements") body = sprintf( "%-=78s", body ) + this_player()->append_signature(); bing = (class info_written)being_written[ this_player()->query_name() ]; if ( !BOARD_HAND->add_message( board_name, capitalize( (string)this_player()->query_name() ), bing->subject, body, bing->note_num ) ) { printf( "Error writing message.\n" ); } else { printf("Message posted.\n"); this_player()->adjust_sp(-50); } } else { printf( "No message posted.\n" ); } map_delete(being_written, this_player()->query_name()); return ; } /* end_of_thing() */ int do_eat(int num) { if (!BOARD_HAND->delete_message(board_name, num-1)) { add_failed_mess("Failed to eat note.\n"); return 0; } printf("You viciously tear off and eat note %d.\n", num); say( (string)this_player()->one_short() + " viciously tears off and eats note "+ num +".\n" ); event( users(), "inform", (string)this_player()->query_name() + " eats a note off "+ board_name, "message", this_player() ); return 1; } /* eat() */ int do_followup(int num) { int i; mixed stuff; string s; class info_written bing; stuff = (mixed *)BOARD_HAND->get_subjects(board_name); if (num < 0) { num = sizeof(stuff) + num + 1; } if (num < 1 || num > sizeof(stuff)) { add_failed_mess("No note of that number.\n", ({ })); return 0; } if (this_player()->query_sp() < BOARD_SOCIAL_POINT_COST) { add_failed_mess("You need " + BOARD_SOCIAL_POINT_COST + " social points to post a note.\n"); return 0; } /* * If there is a reply type, means we do something other than * post to this board. */ if (!stuff[num - 1][B_REPLY_TYPE] && !BOARD_HAND->test_can_write(board_name, this_object(), this_player()->query_name())) { add_failed_mess("You cannot followup to this board.\n", ({ })); return 0; } bing = new(class info_written); if (sscanf(stuff[num - 1][B_SUBJECT], "Re:#%d %s", i, s) != 2) { bing->subject = "Re:#1 "+ stuff[num - 1][B_SUBJECT]; } else { bing->subject = "Re:#"+ ( i + 1 ) +" "+ s; } bing->note_num = stuff[num - 1][B_NUM]; being_written[(string)this_player()->query_name()] = bing; printf("Include original post? (y/[n]) "); input_to("include_post", 0, num - 1, stuff[num - 1]); add_succeeded_mess(({ "", "$N looks like $r is " "contemplating a note.\n" }), ({ }) ); return 1; } /* do_followup() */ void include_post(string str, int num, mixed *stuff) { if (!str || str == "" || lower_case(str)[0] != 'y') { printf("No.\n"); this_player()->do_edit(0, "end_of_thing"); return; } if (this_player()->query_name() == "macchirton") { printf("No including notes for pointless and repeated abuse.\n"); this_player()->do_edit(0, "end_of_thing"); return; } this_player()-> do_edit("On " + ctime(stuff[B_TIME]) + ", " + stuff[B_NAME] + " wrote:\n> " + replace_string(BOARD_HAND->get_message(board_name, num), "\n", "\n> ") + "\n", "end_of_thing"); } /* include_post() */ int do_reply(int num) { mixed stuff; stuff = (mixed *)BOARD_HAND->get_subjects(board_name); if (num < 1 || num > sizeof(stuff)) { add_failed_mess("No note of that number.\n", ({ })); return 0; } MAIL_TRACK->mail(stuff[num-1][B_NAME], stuff[num-1][B_SUBJECT]); add_succeeded_mess(({ "", "$N looks like $r is " "contemplating a note.\n" }), ({ }) ); return 1; } /* reply() */ void set_board_name(string str) { board_name = str; } void set_datafile(string str) { board_name = str; } int query_new_messages() { mixed *notes; mapping news_rc; news_rc = BOARD_HAND->query_newsrc(this_player()->query_name()); if (!news_rc) news_rc = ([ ]); notes = (mixed *)BOARD_HAND->get_subjects(board_name); if (!sizeof(notes)) return 0; return (notes[sizeof(notes)-1][B_TIME] > news_rc[board_name]); } /* query_new_messages() */