/* * Copyright 2007 Kevin Roe * This file is part of makeroom. * * makeroom is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Jriver is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ // makeroom.c // // Author: Zanz@Xyddikon-4 (XK4) // // Description: Makeroom is a menu-based program to build // simple rooms without writting any code. // // Although makeroom was designed specifically for our lib, // it should be easy to modify to work with most MUDs running // the LDMud 3.3.* or 3.4.* driver (might work on earlier versions). // // XK4: roia.servegame.org 4000 // Nov07 #define USER this_player()->query_real_name() #define HEADER sprintf("\ // %s\n\ // Created %s\n\ // by %s [RoomMaker]\n\ \n\ #include \"%s\"\n\ \n\ inherit ROOM;\n\ \n\ void create() {\n",\ users[USER]["filename"],\ ctime(time()),\ capitalize(USER),\ users[USER]["hfilename"]) #include <input_to.h> #include <regexp.h> // these are the default values used to init each user private mapping exits = ([ ]); /* exits = ([ "north" : "/path/to/file" ]); */ private mapping details = ([ ]); /* details = ([ "detail": "description of detail" ]); */ private string filename = ""; private string hfilename = "defs.h"; private string planet = "urth"; private string short_desc = "An empty room"; private string long_desc = "This is an empty room yo!\n"; private string color = "c"; // you may need to tailor this or remove color altogether if your // rooms do not support a color for exits. private mapping real_colors = ([ "b": "blue", "B": "b_blue", "c": "cyan", "C": "b_cyan", "g": "green", "G": "b_green", "m": "magenta", "M": "b_magenta", "r": "red", "R": "b_red", "w": "reset", "W": "bold", "y": "brown", "Y": "yellow", "K": "b_black", ]); private string *colors = ({ "b","B","c","C","g","G","m","M","r","R","w","W","y","Y","K" }); private int inside = 1; private int light = 0; private mapping users = ([ ]); private string macro_name(); private void shell_loop(string input); private void exit_submenu(string str); private void detail_submenu(string str); private void get_exit_name(string str); private void mod_exit(string str); private void display_menu(); private void display_exit_menu(); private void display_detail_menu(); private string generate_code(); private void editor(string str) { mapping tmp; tmp = users[USER]; if(!tmp["buffer"]) tmp["buffer"] = ({ }); switch(str) { case "~q": printf("Editor aborted.\n"); tmp["buffer"] = ({ }); apply(#'display_menu); apply(#'shell_loop); return; break; case ".": case "**": switch(tmp["editor"]) { case "long_desc": tmp["long_desc"] = sprintf("%s\n", implode(tmp["buffer"],"\n")); apply(#'display_menu); apply(#'shell_loop); break; case "detail": tmp["details"] += ([ users[USER]["detail_name"] : sprintf("%s\n", implode(tmp["buffer"], "\n")) ]); apply(#'display_detail_menu); input_to(#'detail_submenu, INPUT_PROMPT, "Detail] "); break; default: printf("Unknown option.\n"); break; } tmp["buffer"] = ({ }); return; break; default: tmp["buffer"] += ({ str }); break; } input_to(#'editor, INPUT_PROMPT, "] "); return; } private string exit_string() { int x; string ret = ""; string *names; if(!sizeof(users[USER]["exits"])) return "none"; names = m_indices(users[USER]["exits"]); for(x = 0; x < sizeof(names); x++) { if(x > 0) ret += ", "+names[x]; else ret += names[x]; } ret = sprintf("&%s%s", users[USER]["color"], ret); return ret; } private string detail_string() { int x; string ret = ""; string *names; if(!sizeof(users[USER]["details"])) return "none"; names = m_indices(users[USER]["details"]); for(x = 0; x < sizeof(names); x++) { if(x > 0) ret += ", "+names[x]; else ret += names[x]; } ret = sprintf("&%s%s", users[USER]["color"], ret); return ret; } private void delete_exit(string str) { string *enames = m_indices(users[USER]["exits"]); int choice = to_int(str); if(!choice) { printf("No exit deleted\n"); apply(#'display_exit_menu); input_to(#'exit_submenu, INPUT_PROMPT, "Exit] "); return; } users[USER]["exits"] -= ([ enames[choice-1] ]); apply(#'display_exit_menu); input_to(#'exit_submenu, INPUT_PROMPT, "Exit] "); return; } private void delete_detail(string str) { string *dnames = m_indices(users[USER]["details"]); int choice = to_int(str); if(!choice) { printf("No detail deleted\n"); apply(#'display_detail_menu); input_to(#'detail_submenu, INPUT_PROMPT, "Exit] "); return; } users[USER]["details"] -= ([ dnames[choice-1] ]); apply(#'display_detail_menu); input_to(#'detail_submenu, INPUT_PROMPT, "Exit] "); return; } private void mod_which_exit(string str) { int choice = to_int(str); if(!choice) { printf("No exit modified\n"); apply(#'display_exit_menu); input_to(#'exit_submenu, INPUT_PROMPT, "Exit] "); return; } users[USER]["exit_to_mod"] = choice; users[USER]["old_exit_name"] = m_indices(users[USER]["exits"])[choice-1]; printf("Modify %s how?\n", users[USER]["old_exit_name"]); printf("1 : Change name\n"); printf("2 : Change destination\n"); input_to(#'mod_exit, INPUT_PROMPT, "] "); return; } private void display_exit_menu() { printf("----=Exit Submenu=----\n"); printf("Current exits: %s\n", exit_string()); printf("----------------------\n"); printf("1: Add an exit\n"); printf("2: Delete an exit\n"); printf("3: Modify an exit\n"); printf("x: Return to main menu\n"); return; } private void display_detail_menu() { printf("----=Detail Submenu=----\n"); printf("Current details: %s\n", detail_string()); printf("------------------------\n"); printf("1: Add a detail\n"); printf("2: Delete a detail\n"); printf("3: Modify a detail\n"); printf("x: Return to main menu\n"); return; } private void display_menu() { mapping map = users[USER]; printf("1 : Set filename [%s]\n", map["filename"]); printf("2 : Set header filename [%s]\n", map["hfilename"]); printf("3 : Set short description [%s]\n", map["short_desc"]); printf("4 : Display long description\n"); printf("5 : Set long description\n"); printf("6 : Set planet [%s]\n", map["planet"]); printf("7 : Set inside [%O]\n", map["inside"]); if(users[USER]["inside"] == 1) printf("8 : Set light [%s%O]\n", (map["light"] > 0 ? "" : ""), map["light"]); // the first "" contains an ansi // code for yellow and the second "" // contains an ansi code for // grey/bold_black printf("9 : Exits [%s]\n", exit_string()); printf("10 : Details [%s]\n", detail_string()); printf("11 : Set room color [&%s%s]\n", users[USER]["color"], users[USER]["color"]); printf("w : Generate and write code to file\n"); printf("x : Exit\n"); return; } private void get_exit_path(string str) { if(str == "") { apply(#'display_exit_menu); input_to(#'exit_submenu, INPUT_PROMPT, "Exit] "); return; } users[USER]["exits"] += ([ users[USER]["exit_name"]: str ]); apply(#'display_exit_menu); input_to(#'exit_submenu, INPUT_PROMPT, "Exit] "); return; } private void mod_exit(string str) { int choice = to_int(str); if(!choice) { apply(#'display_exit_menu); apply(#'exit_submenu, "3"); return; } if(choice == 1) { input_to(#'get_exit_name, INPUT_PROMPT, "Enter new exit name: "); } if(choice == 2) { input_to(#'get_exit_path, INPUT_PROMPT, "Enter new destination: "); } return; } private void get_detail_name(string str) { if(str == "") { apply(#'display_detail_menu); input_to(#'detail_submenu, INPUT_PROMPT, "Exit] "); return; } users[USER]["detail_name"] = str; users[USER]["editor"] = "detail"; printf("Enter description of &%s%s:\n", users[USER]["color"], users[USER]["detail_name"]); printf("Type . or ** to save, or ~q to abort.\n"); input_to(#'editor, INPUT_PROMPT, "] "); return; } private void get_exit_name(string str) { if(str == "") { apply(#'display_exit_menu); input_to(#'exit_submenu, INPUT_PROMPT, "Exit] "); return; } users[USER]["exit_name"] = str; if(users[USER]["get_exit_path"]) { input_to(#'get_exit_path, INPUT_PROMPT, "Enter destination: "); users[USER]["get_exit_path"] = 0; } else { mapping temp = users[USER]["exits"]; temp += ([ users[USER]["exit_name"] : temp[users[USER]["old_exit_name"]] ]); temp -= ([ users[USER]["old_exit_name"] ]); users[USER] -= ([ "old_exit_name" ]); apply(#'display_exit_menu); input_to(#'exit_submenu, INPUT_PROMPT, "Exit] "); return; } return; } private void exit_submenu(string str) { string *enames = m_indices(users[USER]["exits"]); switch(str) { case "1": users[USER]["get_exit_path"] = 1; input_to(#'get_exit_name, INPUT_PROMPT, "Enter exit name: "); break; case "2": if(sizeof(enames)) printf("Delete which exit?\n"); else { printf("There are no exits defined.\n"); break; } for(int x = 0; x < sizeof(users[USER]["exits"]); x++) { printf("%-=3O : &%s%s\n", x+1, users[USER]["color"], enames[x]); } input_to(#'delete_exit, INPUT_PROMPT, "] "); break; case "3": if(sizeof(enames)) printf("Modify which exit?\n"); else { printf("There are no exits defined.\n"); break; } for(int x = 0; x < sizeof(users[USER]["exits"]); x++) { printf("%-=3O : &%s%s\n", x+1, users[USER]["color"], enames[x]); } input_to(#'mod_which_exit, INPUT_PROMPT, "] "); break; case "x": apply(#'display_menu); input_to(#'shell_loop, INPUT_PROMPT, "] "); return; break; default: printf("Unknown option.\n"); break; } input_to(#'exit_submenu, INPUT_PROMPT, "Exit] "); } private void detail_submenu(string str) { string *dnames = m_indices(users[USER]["details"]); switch(str) { case "1": input_to(#'get_detail_name, INPUT_PROMPT, "Enter detail name: "); break; case "2": if(sizeof(dnames)) printf("Delete which detail?\n"); else { printf("There are no details defined.\n"); break; } for(int x = 0; x < sizeof(users[USER]["details"]); x++) { printf("%-=3O : &%s%s\n", x+1, users[USER]["color"], dnames[x]); } input_to(#'delete_detail, INPUT_PROMPT, "] "); break; case "3": printf("Not implemented yet\n"); break; if(sizeof(dnames)) printf("Modify which detail?\n"); else { printf("There are no details defined.\n"); break; } for(int x = 0; x < sizeof(users[USER]["details"]); x++) { printf("%-=3O : &%s%s\n", x+1, users[USER]["color"], dnames[x]); } input_to(#'mod_which_exit, INPUT_PROMPT, "] "); break; printf("Delete a detail\n"); break; case "x": apply(#'display_menu); input_to(#'shell_loop, INPUT_PROMPT, "] "); return; break; default: printf("Unknown option.\n"); break; } input_to(#'detail_submenu, INPUT_PROMPT, "Detail] "); } private void get_filename(string input) { input = regreplace(input, " ", "_", RE_GLOBAL); if(input[<2..] != ".c") input += ".c"; users[USER]["filename"] = input; apply(#'display_menu); input_to(#'shell_loop, INPUT_PROMPT, "] "); return; } private void get_hfilename(string input) { input = regreplace(input, " ", "_", RE_GLOBAL); if(input[<2..] != ".h") input += ".h"; users[USER]["hfilename"] = input; apply(#'display_menu); input_to(#'shell_loop, INPUT_PROMPT, "] "); return; } private void get_short(string input) { if(input != "") users[USER]["short_desc"] = input; apply(#'display_menu); input_to(#'shell_loop, INPUT_PROMPT, "] "); return; } private void get_planet(string input) { if(input != "") users[USER]["planet"] = input; apply(#'display_menu); input_to(#'shell_loop, INPUT_PROMPT, "] "); return; } private void get_light(string input) { if(input != "") { if(input != "0" && !to_int(input)) printf("You must enter an integer value!\n"); else users[USER]["light"] = to_int(input); } apply(#'display_menu); input_to(#'shell_loop, INPUT_PROMPT, "] "); return; } private void get_color(string input) { if(input != "" && member(colors, input) != -1) users[USER]["color"] = input; else printf("Error: invalid color code\n"); apply(#'display_menu); input_to(#'shell_loop, INPUT_PROMPT, "] "); return; } private void get_inside(string input) { if(input != "0" && input != "1") { printf("Invalid input, enter 1 for inside, 0 for outside.\n"); input_to(#'get_inside, INPUT_PROMPT, "Enter inside: "); return; } users[USER]["inside"] = to_int(input); apply(#'display_menu); input_to(#'shell_loop, INPUT_PROMPT, "] "); return; } private void verify_write(string input) { if(input == "" || input == "y" || input == "Y") { users[USER]["quit_after_save"] = 1; apply(#'shell_loop, "w"); apply(#'shell_loop, "x"); return; } return; } private void verify_overwrite(string input) { if(input != "y") { printf("Write aborted.\n"); if(users[USER]["quit_after_save"] == 1) { printf("Goodbye.\n"); return; } apply(#'display_menu); input_to(#'shell_loop, INPUT_PROMPT, "] "); return; } users[USER]["overwrite"] = 1; apply(#'shell_loop, "w"); return; } private void write_header() { string hfile; hfile = ""; hfile += sprintf("// %s\n", users[USER]["hfilename"]); hfile += sprintf("// Created %s\n", ctime(time())); hfile += sprintf("// by %s [RoomMaker]\n", capitalize(this_player()->query_real_name())); hfile += "\n"; hfile += sprintf("#define %s(x) sprintf(\"%s/%%s\",x)\n", macro_name(), this_player()->query_path()); write_file(sprintf("%s/%s", this_player()->query_path(), users[USER]["hfilename"]), hfile); printf("Header file [%s] written\n", users[USER]["hfilename"]); return; } private void shell_loop(string input) { switch(input) { case "x": if(!users[USER]["written"] && users[USER]["filename"] != "") { input_to(#'verify_write, INPUT_PROMPT, "Save before exit? (Y/n) "); return; break; } printf("Goodbye.\n"); return; break; case "1": input_to(#'get_filename, INPUT_PROMPT, "Enter filename: "); break; case "2": input_to(#'get_hfilename, INPUT_PROMPT, "Enter header filename: "); break; case "3": input_to(#'get_short, INPUT_PROMPT, "Enter short description: "); break; case "5": printf("Enter new long description:\n"); printf("Type . or ** to save, ~q to abort.\n"); users[USER]["editor"] = "long_desc"; input_to(#'editor, INPUT_PROMPT, "] "); break; case "4": printf("Current long description:\n"); printf("------------------------\n"); printf("%s", users[USER]["long_desc"]); printf("------------------------\n"); apply(#'display_menu); break; case "6": input_to(#'get_planet, INPUT_PROMPT, "Enter planet: "); break; case "7": input_to(#'get_inside, INPUT_PROMPT, "Set inside (0 = outside, 1 = inside): "); break; case "8": if(users[USER]["inside"] == 0) { printf("Error: you must set inside to 1 first.\n"); apply(#'display_menu); break; } input_to(#'get_light, INPUT_PROMPT, "Enter light: "); break; case "9": apply(#'display_exit_menu); input_to(#'exit_submenu, INPUT_PROMPT, "Exit] "); break; case "10": apply(#'display_detail_menu); input_to(#'detail_submenu, INPUT_PROMPT, "Detail] "); break; case "11": printf("Valid color codes = b B c C g G m M r R w W y Y K\n"); input_to(#'get_color, INPUT_PROMPT, "Enter color code: "); break; case "w": string current_path = this_player()->query_path(); string final = sprintf("%s/%s", current_path, users[USER]["filename"]); if(!users[USER]["overwrite"]) if(file_size(final) != -1) { printf("Warning: file already exists.\n"); input_to(#'verify_overwrite, INPUT_PROMPT, "Overwrite? (y/N) "); return; break; } string file = generate_code(); if(file == "") { printf("Error generating code.\n"); break; } if(file_size(this_player()->query_path()+"/"+ users[USER]["hfilename"]) == -1) write_header(); printf("Writing %s\n", final); if(users[USER]["overwrite"]) write_file(final, file, 1); else write_file(final, file); printf("Write completed.\n"); users[USER]["overwrite"] = 0; users[USER]["written"] = 1; if(users[USER]["quit_after_save"] == 1) { return; break; } apply(#'display_menu); break; default: printf("Unknown option.\n"); break; } input_to(#'shell_loop, INPUT_PROMPT, "] "); return; } private void init_user() { users -= ([ USER ]); users += ([ USER : ([ "filename": filename, "hfilename": hfilename, "planet": planet, "inside": inside, "light": light, "short_desc": short_desc, "long_desc": long_desc, "color": color, "exits": ([ ]), "details": ([ ]), "overwrite": 0, ]) ]); } private string macro_name() { string current = this_player()->query_path(); string *split = explode(current, "/"); return upper_case(split[sizeof(split)-1]); } // This is where you would make sure the code that is generated // works for your lib. private string generate_code() { string file = ""; string *long = explode(users[USER]["long_desc"],"\n")-({""}); string current_path = this_player()->query_path(); string final = sprintf("%s/%s", current_path, users[USER]["filename"]); if(users[USER]["filename"] == "") return printf("Invalid filename!\n"),""; file += sprintf("%s\n", HEADER); file += sprintf(" set_short(\"%s\");\n", users[USER]["short_desc"]); file += " set_long("; for(int x = 0; x < sizeof(long); x++) { long[x] += "\\n"; if(x == sizeof(long)-1) file += sprintf("%s%O);\n", (x == 0 ? "" : " "), /* controls indentation */ long[x]); else { file += sprintf("%s%O+\n", (x == 0 ? "" : " "), long[x]); } } if(users[USER]["inside"] == 1) { file += sprintf(" set_property(\"inside\",1);\n"); file += sprintf(" set_light(%O);\n", users[USER]["light"]); } file += sprintf(" set_planet(\"%s\");\n", users[USER]["planet"]); file += sprintf(" short_color = \"%s\";", real_colors[users[USER]["color"]]); file += "\n\n exits = ([\n"; for(int x = 0; x < sizeof(users[USER]["exits"]); x++) { string *enames = m_indices(users[USER]["exits"]); file += sprintf(" %O : %s(%O),\n", enames[x], macro_name(), users[USER]["exits"][enames[x]]); } file += " ]);\n"; file += "\n details = ([\n"; for(int x = 0; x < sizeof(users[USER]["details"]); x++) { string *dnames = m_indices(users[USER]["details"]); string *desc = explode(users[USER]["details"][dnames[x]],"\n")-({""}); file += sprintf(" %O : ", dnames[x]); for(int y = 0; y < sizeof(desc); y++) { if(y != sizeof(desc)-1) desc[y] += "\\n"; if(y == sizeof(desc)-1) file += sprintf("%s%O,\n", (y == 0 ? "" : " "), /* indentation again */ desc[y]); else file += sprintf("%s%O+\n", (y == 0 ? "" : " "), desc[y]); } } file += " ]);\n"; file += "\n return;\n"; file += "}\n"; return file; } // this is the function that gets called to start the program public status main(string str) { string current = this_player()->query_path()+"/"; if(!this_player()->valid_write(current, 1)) return printf("You do not have write access to %s\n", current),1; printf("[=-----RoomMakerV1-----=]\n"); apply(#'init_user); apply(#'display_menu); input_to(#'shell_loop, INPUT_PROMPT, "] "); return 1; }