#include <stdio.h> #include <stdlib.h> #include <limits.h> #include <string.h> #include "include/structs.h" #include "include/main.h" #include "include/utils.h" #include "include/parse_wiley.h" #define _REPORTS_C #include "include/dump_report.h" void make_zone_report(zones *Zones, rooms *Rooms, objects *Objects, mobs *Mobs, char *outfile) { FILE *ofp; register int i, j; int LeaderMob, LastMob, LastLoc; if (outfile && *outfile) { if (!Quiet) { fprintf(stderr, "Generating Zone reports..."); fflush(stderr); } ofp = open_file(outfile, "w"); for (i = j = 0; i < Zones->Count; i++) j += Zones->Zone[i].Count; fprintf(ofp, "ZONE REPORT: %d total commands found in %d zones.\n", j, Zones->Count); for (i = 0; i < Zones->Count; i++) { if (!Quiet) spin(stderr); LastMob = LastLoc = LeaderMob = -1; fprintf(ofp, "Zone \"%s\"[#%d] spans rooms (#%d,#%d)\n", Zones->Zone[i].Name, Zones->Zone[i].Number, (!i ? 0 : Zones->Zone[i - 1].Top + 1), Zones->Zone[i].Top); if (Zones->Zone[i].Mode == ZONE_RESET_PC) fprintf(ofp, " It resets every %d minutes, if no players are present\n", Zones->Zone[i].Time); else if (Zones->Zone[i].Mode == ZONE_RESET_ALWAYS) fprintf(ofp, " It always resets every %d minutes\n", Zones->Zone[i].Time); else if (Zones->Zone[i].Mode == ZONE_RESET_NEVER) fprintf(ofp, " It does not reset\n"); else fprintf(ofp, " It resets in some undefined fashion\n"); if (Zones->Zone[i].Count) fprintf(ofp, " There are %d Commands defined:\n", Zones->Zone[i].Count); else fprintf(ofp, " There are no Commands in this Zone.\n"); for (j = 0; j < Zones->Zone[i].Count; j++) { fprintf(ofp, " [%3d] ", j); switch (Zones->Zone[i].Cmds[j].Command) { case ZONE_CMD_MOBILE: LastMob = Zones->Zone[i].Cmds[j].Arg[ZONE_MOBILE]; LastLoc = Zones->Zone[i].Cmds[j].Arg[ZONE_ROOM]; LeaderMob = LastMob; fprintf(ofp, "Load Mobile \"%s\"[#%d] to \"%s\"[#%d]\n", mob_name(Mobs, Zones->Zone[i].Cmds[j].Arg[ZONE_MOBILE]), Zones->Zone[i].Cmds[j].Arg[ZONE_MOBILE], room_name(Rooms, Zones->Zone[i].Cmds[j].Arg[ZONE_ROOM]), Zones->Zone[i].Cmds[j].Arg[ZONE_ROOM]); break; case ZONE_CMD_OBJECT: fprintf(ofp, "Load Object \"%s\"[#%d] to \"%s\"[#%d]\n", obj_name(Objects, Zones->Zone[i].Cmds[j].Arg[ZONE_OBJECT]), Zones->Zone[i].Cmds[j].Arg[ZONE_OBJECT], room_name(Rooms, Zones->Zone[i].Cmds[j].Arg[ZONE_ROOM]), Zones->Zone[i].Cmds[j].Arg[ZONE_ROOM]); break; case ZONE_CMD_GIVE: fprintf(ofp, "Give Object \"%s\"[#%d] to Mobile \"%s\"[#%d]\n", obj_name(Objects, Zones->Zone[i].Cmds[j].Arg[ZONE_OBJECT]), Zones->Zone[i].Cmds[j].Arg[ZONE_OBJECT], mob_name(Mobs, LastMob), LastMob); break; case ZONE_CMD_EQUIP: fprintf(ofp, "Object \"%s\"[#%d] is %s by Mobile \"%s\"[#%d]\n", obj_name(Objects, Zones->Zone[i].Cmds[j].Arg[ZONE_OBJECT]), Zones->Zone[i].Cmds[j].Arg[ZONE_OBJECT], equip_name(Zones->Zone[i].Cmds[j].Arg[ZONE_POSITION]), mob_name(Mobs, LastMob), LastMob); break; case ZONE_CMD_PUT: fprintf(ofp, "Put Object \"%s\"[#%d] into Object \"%s\"[#%d]\n", obj_name(Objects, Zones->Zone[i].Cmds[j].Arg[ZONE_OBJECT]), Zones->Zone[i].Cmds[j].Arg[ZONE_OBJECT], obj_name(Objects, Zones->Zone[i].Cmds[j].Arg[ZONE_TARGET_OBJ]), Zones->Zone[i].Cmds[j].Arg[ZONE_TARGET_OBJ]); break; case ZONE_CMD_DOOR: fprintf(ofp, "Reset %s door of \"%s\"[#%d] to %s\n", exit_name(Zones->Zone[i].Cmds[j].Arg[ZONE_DOOR_EXIT]), room_name(Rooms, Zones->Zone[i].Cmds[j].Arg[ZONE_ROOM]), Zones->Zone[i].Cmds[j].Arg[ZONE_DOOR_ROOM], doorstate_name(Zones->Zone[i].Cmds[j].Arg[ZONE_DOOR_STATE])); break; case ZONE_CMD_REMOVE: fprintf(ofp, "Remove Object \"%s\"[#%d] from \"%s\"[#%d]\n", obj_name(Objects, Zones->Zone[i].Cmds[j].Arg[ZONE_REMOVE_OBJ]), Zones->Zone[i].Cmds[j].Arg[ZONE_REMOVE_OBJ], room_name(Rooms, Zones->Zone[i].Cmds[j].Arg[ZONE_ROOM]), Zones->Zone[i].Cmds[j].Arg[ZONE_REMOVE_ROOM]); break; case ZONE_CMD_LEAD: fprintf(ofp, "Load Mobile \"%s\"[#%d] to \"%s\"[#%d], led by Mobile \"%s\"[#%d]\n", mob_name(Mobs, Zones->Zone[i].Cmds[j].Arg[ZONE_MOBILE]), Zones->Zone[i].Cmds[j].Arg[ZONE_MOBILE], room_name(Rooms, LastLoc), LastLoc, mob_name(Mobs, LeaderMob), LeaderMob); LastMob = Zones->Zone[i].Cmds[j].Arg[ZONE_MOBILE]; break; case ZONE_CMD_HATE: fprintf(ofp, "Cause Mobile \"%s\"[#%d] in \"%s\"[#%d] to HATE %s\n", mob_name(Mobs, LastMob), LastMob, room_name(Rooms, LastLoc), LastLoc, hate_name(Zones->Zone[i].Cmds[j].Arg[ZONE_HATE_TYPE], Zones->Zone[i].Cmds[j].Arg[ZONE_HATE_VALUE]) ); /* * LastMob= Zones->Zone[i].Cmds[j].Arg[ZONE_MOBILE]; */ break; default: fprintf(ofp, "Unrecognized command '%c'?\n", Zones->Zone[i].Cmds[j].Command); break; } } fprintf(ofp, "\n"); } fclose(ofp); if (!Quiet) fprintf(stderr, "done.\n"); } } void make_shop_report(zones *Zones, rooms *Rooms, objects *Objects, mobs *Mobs, shops *Shops, char *outfile) { FILE *ofp; register int i, j; if (outfile && *outfile) { if (!Quiet) { fprintf(stderr, "Generating Shop reports..."); fflush(stderr); } ofp = open_file(outfile, "w"); fprintf(ofp, "SHOP REPORT: %d Shops found.\n", Shops->Count); for (i = 0; i < Shops->Count; i++) { if (!Quiet) spin(stderr); fprintf(ofp, "Shop#%d is at \"%s\"[#%d], owned by Mobile \"%s\"[#%d] (", Shops->Shop[i].Number, room_name(Rooms, Shops->Shop[i].Room), Shops->Shop[i].Room, mob_name(Mobs, Shops->Shop[i].Keeper), Shops->Shop[i].Keeper); fprintf(ofp, "%s) (", shop_attitude_name(Shops->Shop[i].Attitude)); fprintf(ofp, "%s)\n", shop_immortal_name(Shops->Shop[i].Immortal)); fprintf(ofp, " It sells at %lf list, and buys at %lf list.\n", Shops->Shop[i].Selling, Shops->Shop[i].Buying); fprintf(ofp, " It is "); if (Shops->Shop[i].Close == 28) fprintf(ofp, "Always Open\n"); else fprintf(ofp, "Open from %d to %d\n", Shops->Shop[i].Open, Shops->Shop[i].Close); fprintf(ofp, " It Sells: "); if (Shops->Shop[i].SellCount) { for (j = 0; j < Shops->Shop[i].SellCount; j++) if (Shops->Shop[i].Sell[j] >= 0) fprintf(ofp, "Object \"%s\"[#%d] ", obj_name(Objects, Shops->Shop[i].Sell[j]), Shops->Shop[i].Sell[j]); fprintf(ofp, "\n"); } else fprintf(ofp, "nothing\n"); fprintf(ofp, " It Trades: "); if (Shops->Shop[i].TradeCount) { for (j = 0; j < Shops->Shop[i].TradeCount; j++) if (Shops->Shop[i].Trade[j]) fprintf(ofp, "Object Type %d ", Shops->Shop[i].Trade[j]); fprintf(ofp, "\n"); } else fprintf(ofp, "nothing\n"); for (j = 0; j < Shops->Shop[i].MessageCount; j++) fprintf(ofp, " Message %d: \"%s\"\n", j, Shops->Shop[i].Message[j]); fprintf(ofp, "\n"); } fclose(ofp); if (!Quiet) fprintf(stderr, "done.\n"); } } void make_room_report(zones *Zones, rooms *Rooms, char *outfile) { FILE *ofp; register int i, j, Sum; if (outfile && *outfile) { if (!Quiet) { fprintf(stderr, "Generating Room reports..."); fflush(stderr); } ofp = open_file(outfile, "w"); fprintf(ofp, "ROOM REPORT: %d rooms found.\n", Rooms->Count); for (i = 0; i < Rooms->Count; i++) { if (!Quiet) spin(stderr); fprintf(ofp, "Room \"%s\"[#%d] belongs to zone \"%s\"[#%d]\n", room_name(Rooms, Rooms->Room[i].Number), Rooms->Room[i].Number, zone_name(Zones, Rooms->Room[i].Zone), Rooms->Room[i].Zone); fprintf(ofp, " It is a \"%s\" room, with a %zd byte description\n", sector_name(Rooms->Room[i].Sector), strlen(Rooms->Room[i].Description)); if (Rooms->Room[i].ExtraCount) { for (j = Sum = 0; j < Rooms->Room[i].ExtraCount; j++) Sum += strlen(Rooms->Room[i].Extra[j].Description); fprintf(ofp, " This room has %d Extra Descriptions (%d bytes)\n", Rooms->Room[i].ExtraCount, Sum); } if (Rooms->Room[i].Sector == SECT_TELEPORT) { fprintf(ofp, " This room is treated as \"%s\" for movement purposes\n", sector_name(Rooms->Room[i].TeleportSector)); fprintf(ofp, " After %d ticks, it will teleport you to \"%s\"[#%d]\n", Rooms->Room[i].TeleportTime / 10, room_name(Rooms, Rooms->Room[i].TeleportTo), Rooms->Room[i].TeleportTo); if (Rooms->Room[i].TeleportLook) fprintf(ofp, " Which you will automatically look at\n"); } else if (Rooms->Room[i].Sector == SECT_WATER_NOSWIM) { fprintf(ofp, " This room will move you through the %s exit in %d ticks\n", exit_name(Rooms->Room[i].RiverDirection), Rooms->Room[i].RiverSpeed / 10); } fprintf(ofp, " Flags: %s\n", room_flags(Rooms->Room[i].Flags)); if (Rooms->Room[i].Flags & ROOM_SOUND) { if (Rooms->Room[i].SoundCount > 0) fprintf(ofp, " The sound heard inside the room is:\n \"%s\"\n", Rooms->Room[i].SoundText[0]); if (Rooms->Room[i].SoundCount > 1) fprintf(ofp, " The sound heard in adjacent room is:\n \"%s\"\n", Rooms->Room[i].SoundText[1]); } for (j = 0; j < Rooms->Room[i].ExitCount; j++) { switch (Rooms->Room[i].Exit[j].Error) { case EXIT_OK: fprintf(ofp, " The %s exit is %s, which leads to \"%s\"[#%d]\n", exit_name(Rooms->Room[i].Exit[j].Direction), exittype_name(Rooms->Room[i].Exit[j].Type), room_name(Rooms, Rooms->Room[i].Exit[j].Room), Rooms->Room[i].Exit[j].Room); break; case EXIT_NON_EUCLIDEAN: fprintf(ofp, " The (non-euclidean) %s exit is %s, which leads to \"%s\"[#%d]\n", exit_name(Rooms->Room[i].Exit[j].Direction), exittype_name(Rooms->Room[i].Exit[j].Type), room_name(Rooms, Rooms->Room [i].Exit [j].Room), Rooms->Room[i].Exit[j].Room); { EXIT *foreign; foreign = &Rooms->Room[Rooms->Room[i].Exit[j]. RoomIndex].Exit[RevDir[Rooms->Room[i].Exit[j]. Direction]]; fprintf(ofp, " The matching %s exit in \"%s\"[#%d] goes to \"%s\"[#%d] instead!\n", exit_name(foreign->Direction), room_name(Rooms, Rooms-> Room[i].Exit[j]. Room), Rooms->Room[i].Exit[j].Room, room_name(Rooms, foreign->Room), foreign->Room); } break; case EXIT_ONE_WAY: fprintf(ofp, " The (one-way) %s exit is %s, which leads to \"%s\"[#%d]\n", exit_name(Rooms->Room[i].Exit[j].Direction), exittype_name(Rooms->Room[i].Exit[j].Type), room_name(Rooms, Rooms->Room [i].Exit [j].Room), Rooms->Room[i].Exit[j].Room); break; case EXIT_DESCRIPTION_ONLY: fprintf(ofp, " The %s exit is for description only.\n", exit_name(Rooms->Room[i].Exit[j].Direction)); break; } } fprintf(ofp, "\n"); } fclose(ofp); if (!Quiet) fprintf(stderr, "done.\n"); } } void make_obj_report(zones *Zones, objects *Objects, char *outfile) { FILE *ofp; register int i, j, Sum; if (outfile && *outfile) { if (!Quiet) { fprintf(stderr, "Generating Object reports..."); fflush(stderr); } ofp = open_file(outfile, "w"); fprintf(ofp, "OBJECT REPORT: %d Objects found.\n", Objects->Count); for (i = 0; i < Objects->Count; i++) { if (!Quiet) spin(stderr); fprintf(ofp, "Object \"%s\"[#%d] is known by the id string \"%s\"\n", obj_name(Objects, Objects->Object[i].Number), Objects->Object[i].Number, Objects->Object[i].Name); fprintf(ofp, " It belongs to zone \"%s\"[#%d]\n", zone_name(Zones, Objects->Object[i].Zone), Objects->Object[i].Zone); if (Objects->Object[i].Value < 0) fprintf(ofp, " It weighs %d units and cannot be sold, costing %d to rent.\n", Objects->Object[i].Weight, Objects->Object[i].Rent); else fprintf(ofp, " It weighs %d units and is worth %d gold, costing %d to rent.\n", Objects->Object[i].Weight, Objects->Object[i].Value, Objects->Object[i].Rent); if (Objects->Object[i].Description && *(Objects->Object[i].Description)) fprintf(ofp, " It has a %zd byte long description\n \"%s\"\n", strlen(Objects->Object[i].Description), Objects->Object[i].Description); if (Objects->Object[i].ActionDesc && *(Objects->Object[i].ActionDesc)) fprintf(ofp, " It has a %zd byte action description\n \"%s\"\n", strlen(Objects->Object[i].ActionDesc), Objects->Object[i].ActionDesc); if (Objects->Object[i].ExtraCount) { for (j = Sum = 0; j < Objects->Object[i].ExtraCount; j++) Sum += strlen(Objects->Object[i].Extra[j].Description); fprintf(ofp, " This object has %d Extra Descriptions (%d bytes)\n", Objects->Object[i].ExtraCount, Sum); } if (Objects->Object[i].Flags.Wear) fprintf(ofp, " It can be %s\n", item_wear_name(Objects->Object[i].Flags.Wear)); if (Objects->Object[i].Flags.Extra) fprintf(ofp, " It has these flags: %s\n", item_flag_name(Objects->Object[i].Flags.Extra)); switch (Objects->Object[i].Type) { case ITEM_LIGHT: fprintf(ofp, " This is a light source, lasting %d ticks.\n", Objects->Object[i].Flags.Value[2]); fprintf(ofp, " It of type %d and has colour %d\n", Objects->Object[i].Flags.Value[1], Objects->Object[i].Flags.Value[0]); break; case ITEM_SCROLL: case ITEM_POTION: fprintf(ofp, " This is a level %d %s, containing the spells:\n", Objects->Object[i].Flags.Value[0], (Objects->Object[i].Type == ITEM_SCROLL) ? "scroll" : "potion"); for (j = 1; j < 4; j++) if (Objects->Object[i].Flags.Value[j]) fprintf(ofp, " %s\n", spell_name(Objects->Object[i].Flags.Value[j])); break; case ITEM_WAND: case ITEM_STAFF: fprintf(ofp, " This is a level %d %s, charged with %d of %d %s spells.\n", Objects->Object[i].Flags.Value[0], (Objects->Object[i].Type == ITEM_WAND) ? "wand" : "staff", Objects->Object[i].Flags.Value[2], Objects->Object[i].Flags.Value[1], spell_name(Objects->Object[i].Flags.Value[3])); break; case ITEM_WEAPON: case ITEM_FIREWEAPON: case ITEM_MISSILE: fprintf(ofp, " This is a %s, doing %dd%d %s damage.\n", ((Objects->Object[i].Type == ITEM_WEAPON) ? ((Objects->Object[i].Type == ITEM_FIREWEAPON) ? "fire-weapon" : "weapon") : "missile"), Objects->Object[i].Flags.Value[1], Objects->Object[i].Flags.Value[2], damage_name(Objects->Object[i].Flags.Value[3])); fprintf(ofp, " It has a %d To-Hit factor\n", Objects->Object[i].Flags.Value[0]); break; case ITEM_ARMOR: fprintf(ofp, " This is armour, worth %d.%d of a maximum %d.%d AC units.\n", Objects->Object[i].Flags.Value[0] / 10, Objects->Object[i].Flags.Value[0] - ((Objects->Object[i].Flags.Value[0] / 10) * 10), Objects->Object[i].Flags.Value[1] / 10, Objects->Object[i].Flags.Value[1] - ((Objects->Object[i].Flags.Value[1] / 10) * 10)); break; case ITEM_TRAP: fprintf(ofp, " This is a level %d trap!\n", Objects->Object[i].Flags.Value[0]); fprintf(ofp, " It has %d charges, doing %d type attack with %d damage class\n", Objects->Object[i].Flags.Value[3], Objects->Object[i].Flags.Value[1], Objects->Object[i].Flags.Value[2]); break; case ITEM_CONTAINER: if (Objects->Object[i].Flags.Value[3]) fprintf(ofp, " This is a corpse, which can hold %d units\n", Objects->Object[i].Flags.Value[0]); else { fprintf(ofp, " This is a container, it has a lock of type %d\n", Objects->Object[i].Flags.Value[1]); fprintf(ofp, " It can hold %d units\n", Objects->Object[i].Flags.Value[0]); } break; case ITEM_DRINKCON: fprintf(ofp, " This is a fluid container, it can hold %d units\n", Objects->Object[i].Flags.Value[0]); fprintf(ofp, " It contains %d units of %s, and is %spoisoned\n", Objects->Object[i].Flags.Value[1], liquid_name(Objects->Object[i].Flags.Value[2]), (Objects->Object[i].Flags.Value[1] ? "" : "not ")); break; case ITEM_NOTE: fprintf(ofp, " This is a note, written in language %d\n", Objects->Object[i].Flags.Value[0]); break; case ITEM_KEY: fprintf(ofp, " This is a key of type %d\n", Objects->Object[i].Flags.Value[0]); break; case ITEM_FOOD: fprintf(ofp, " This is food worth %d units, and is %spoisoned\n", Objects->Object[i].Flags.Value[0], (Objects->Object[i].Flags.Value[3] ? "" : "not ")); break; case ITEM_MONEY: fprintf(ofp, " This is money, worth %d gold\n", Objects->Object[i].Flags.Value[0]); break; case ITEM_TRASH: fprintf(ofp, " This is trash\n"); break; case ITEM_PEN: fprintf(ofp, " This is a pen\n"); break; case ITEM_BOARD: fprintf(ofp, " This is a bulletin board\n"); break; case ITEM_BOAT: fprintf(ofp, " This is a boat\n"); break; case ITEM_WORN: fprintf(ofp, " This is a worn item\n"); break; default: fprintf(ofp, " The object is of type \"%s\".\n", item_type_name(Objects->Object[i].Type)); fprintf(ofp, " The internal values are: %d %d %d %d\n", Objects->Object[i].Flags.Value[0], Objects->Object[i].Flags.Value[1], Objects->Object[i].Flags.Value[2], Objects->Object[i].Flags.Value[3]); } if (Objects->Object[i].AffectCount) { for (j = 0; j < Objects->Object[i].AffectCount; j++) switch (Objects->Object[i].Affect[j].location) { case APPLY_SPELL: case APPLY_WEAPON_SPELL: fprintf(ofp, " This object contains a %s of %s\n", apply_name(Objects->Object[i].Affect[j].location), spell_name(Objects->Object[i].Affect[j].modifier)); break; default: fprintf(ofp, " This object affects %s with modifier %d\n", apply_name(Objects->Object[i].Affect[j].location), Objects->Object[i].Affect[j].modifier); break; } } } fclose(ofp); if (!Quiet) fprintf(stderr, "done.\n"); } } void make_mob_report(zones *Zones, mobs *Mobs, char *outfile) { FILE *ofp; register int i, j; /* , Sum; */ if (outfile && *outfile) { if (!Quiet) { fprintf(stderr, "Generating Mob reports..."); fflush(stderr); } ofp = open_file(outfile, "w"); fprintf(ofp, "MOB REPORT: %d Mobs found.\n", Mobs->Count); for (i = 0; i < Mobs->Count; i++) { if (!Quiet) spin(stderr); fprintf(ofp, "Mob \"%s\"[#%d] is known by the id string \"%s\"\n", mob_name(Mobs, Mobs->Mob[i].Number), Mobs->Mob[i].Number, Mobs->Mob[i].Name); fprintf(ofp, " It belongs to zone \"%s\"[#%d]\n", zone_name(Zones, Mobs->Mob[i].Zone), Mobs->Mob[i].Zone); if (Mobs->Mob[i].LongDesc && *(Mobs->Mob[i].LongDesc)) fprintf(ofp, " It has a %zd byte long (room) description\n \"%s\"\n", strlen(Mobs->Mob[i].LongDesc), Mobs->Mob[i].LongDesc); if (Mobs->Mob[i].Description && *(Mobs->Mob[i].Description)) fprintf(ofp, " It has a %zd byte look-at description\n \"%s\"\n", strlen(Mobs->Mob[i].Description), Mobs->Mob[i].Description); fprintf(ofp, " It is a %s %s %s, standing %dcm tall and weighing %dlbs\n", alignment_name(Mobs->Mob[i].Alignment), sex_name(Mobs->Mob[i].Sex), race_name(Mobs->Mob[i].Race), Mobs->Mob[i].Height, Mobs->Mob[i].Weight); fprintf(ofp, " It has attained %d%s Level in these classes: %s\n", Mobs->Mob[i].Level, ordinal(Mobs->Mob[i].Level), class_name(Mobs->Mob[i].Class)); fprintf(ofp, " It has %dd%d%c%d hp, %d mana, and %d move\n", Mobs->Mob[i].HitPoints.Rolls, Mobs->Mob[i].HitPoints.Die, (Mobs->Mob[i].HitPoints.Modifier < 0) ? '-' : '+', Mobs->Mob[i].HitPoints.Modifier, Mobs->Mob[i].ManaPoints, Mobs->Mob[i].MovePoints); fprintf(ofp, " It has an AC of %d, and a THAC0 of %d\n", Mobs->Mob[i].ArmourClass, Mobs->Mob[i].ToHit); if (Mobs->Mob[i].AttackCount) { fprintf(ofp, " It gets %d attacks\n", Mobs->Mob[i].AttackCount); for (j = 0; j < Mobs->Mob[i].AttackCount; j++) fprintf(ofp, " It has a %s attack for %dd%d%c%d damage\n", damage_name(Mobs->Mob[i].Attack[j].Type), Mobs->Mob[i].Attack[j].Rolls, Mobs->Mob[i].Attack[j].Die, (Mobs->Mob[i].Attack[j].Modifier < 0) ? '-' : '+', Mobs->Mob[i].Attack[j].Modifier); } fprintf(ofp, " It carries %dd%d%c%d gold and is worth %dd%d%c%d experience\n", Mobs->Mob[i].Gold.Rolls, Mobs->Mob[i].Gold.Die, (Mobs->Mob[i].Gold.Modifier < 0) ? '-' : '+', Mobs->Mob[i].Gold.Modifier, Mobs->Mob[i].Experience.Rolls, Mobs->Mob[i].Experience.Die, (Mobs->Mob[i].Experience.Modifier < 0) ? '-' : '+', Mobs->Mob[i].Experience.Modifier); fprintf(ofp, " Its stats are: STR %dd%d%c%d / %dd%d%c%d\n", Mobs->Mob[i].Strength.Rolls, Mobs->Mob[i].Strength.Die, (Mobs->Mob[i].Strength.Modifier < 0) ? '-' : '+', Mobs->Mob[i].Strength.Modifier, Mobs->Mob[i].ExtraStrength.Rolls, Mobs->Mob[i].ExtraStrength.Die, (Mobs->Mob[i].ExtraStrength.Modifier < 0) ? '-' : '+', Mobs->Mob[i].ExtraStrength.Modifier); fprintf(ofp, " DEX %dd%d%c%d\n", Mobs->Mob[i].Dexterity.Rolls, Mobs->Mob[i].Dexterity.Die, (Mobs->Mob[i].Dexterity.Modifier < 0) ? '-' : '+', Mobs->Mob[i].Dexterity.Modifier); fprintf(ofp, " CON %dd%d%c%d\n", Mobs->Mob[i].Constitution.Rolls, Mobs->Mob[i].Constitution.Die, (Mobs->Mob[i].Constitution.Modifier < 0) ? '-' : '+', Mobs->Mob[i].Constitution.Modifier); fprintf(ofp, " INT %dd%d%c%d\n", Mobs->Mob[i].Intelligence.Rolls, Mobs->Mob[i].Intelligence.Die, (Mobs->Mob[i].Intelligence.Modifier < 0) ? '-' : '+', Mobs->Mob[i].Intelligence.Modifier); fprintf(ofp, " WIS %dd%d%c%d\n", Mobs->Mob[i].Wisdom.Rolls, Mobs->Mob[i].Wisdom.Die, (Mobs->Mob[i].Wisdom.Modifier < 0) ? '-' : '+', Mobs->Mob[i].Wisdom.Modifier); if (Mobs->Mob[i].Immunity) fprintf(ofp, " It is immune to %s\n", immunity_name(Mobs->Mob[i].Immunity)); if (Mobs->Mob[i].Resistance) fprintf(ofp, " It is resistant to %s\n", immunity_name(Mobs->Mob[i].Resistance)); if (Mobs->Mob[i].Susceptible) fprintf(ofp, " It is susceptible to %s\n", immunity_name(Mobs->Mob[i].Susceptible)); fprintf(ofp, " Its saving throws are: %d %d %d %d %d\n", Mobs->Mob[i].SavingThrow[0], Mobs->Mob[i].SavingThrow[1], Mobs->Mob[i].SavingThrow[2], Mobs->Mob[i].SavingThrow[3], Mobs->Mob[i].SavingThrow[4]); fprintf(ofp, " It loads in %s, and has a default position of %s\n", position_name(Mobs->Mob[i].Position), position_name(Mobs->Mob[i].DefaultPosition)); if (Mobs->Mob[i].ActFlags) fprintf(ofp, " It has the following ACT flags set: %s\n", act_name(Mobs->Mob[i].ActFlags)); if (Mobs->Mob[i].AffectedBy) fprintf(ofp, " It is affected by: %s\n", affected_by_name(Mobs->Mob[i].AffectedBy)); if (Mobs->Mob[i].Sound && *Mobs->Mob[i].Sound) fprintf(ofp, " It makes a local sound\n \"%s\"\n", Mobs->Mob[i].Sound); if (Mobs->Mob[i].DistantSound && *Mobs->Mob[i].DistantSound) fprintf(ofp, " It makes a sound in adjacent rooms\n \"%s\"\n", Mobs->Mob[i].DistantSound); if (Mobs->Mob[i].SkillCount) for (j = 0; j < Mobs->Mob[i].SkillCount; j++) fprintf(ofp, " It knows %s\"%s\" at %d%%\n", (Mobs->Mob[i].Skill[j].Recognise ? "and can recognise " : ""), spell_name(Mobs->Mob[i].Skill[j].Number), Mobs->Mob[i].Skill[j].Learned); } fclose(ofp); if (!Quiet) fprintf(stderr, "done.\n"); } }