diff --git a/src/doors/dgnlance/combat.c b/src/doors/dgnlance/combat.c
new file mode 100644
index 0000000000000000000000000000000000000000..9de9979f695a4a655139b90afd1db9a11728885d
--- /dev/null
+++ b/src/doors/dgnlance/combat.c
@@ -0,0 +1,465 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "xpdev.h"
+#include "dgnlnce.h"
+#include "fileutils.h"
+#include "userfile.h"
+#include "utils.h"
+
+double
+tohit(struct playertype * attacker, struct playertype * defender)
+{
+    return ((attacker->attack * attacker->strength * attacker->dexterity * (xp_random(5) + 1) * attacker->vary) /
+	    (defender->armour * defender->dexterity * defender->luck * defender->vary));
+}
+
+double
+damage(struct playertype * attacker, struct playertype * defender)
+{
+    return ((attacker->power * attacker->strength * (xp_random(5) + 1) * (xp_random(5) + 1) * attacker->vary) /
+	    ((defender->armour) * defender->luck * defender->vary));
+}
+
+void
+endofbattle(BOOL won)
+{
+    int             bt;
+    int             d;
+    FILE           *outfile;
+    char            lstr[5];
+    char            wstr[5];
+    struct playertype *winner;
+    struct playertype *loser;
+    if (opp.status != MONSTER)
+	loaduser(opp.name, TRUE, &tmpuser);
+    if (won) {
+	winner = &user;
+	loser = &tmpuser;
+	SAFECOPY(lstr, sexstrings(loser, HIS, FALSE));
+	SAFECOPY(wstr, "You");
+    } else {
+	winner = &tmpuser;
+	loser = &user;
+	SAFECOPY(lstr, sexstrings(winner, HIS, FALSE));
+	SAFECOPY(lstr, "your");
+	opp.experience = user.experience / 10;
+    }
+    if (opp.status == MONSTER)
+	opp.gold = opp.gold * supplant();
+    nl();
+    if (won)
+	od_printf("You take %s %" QWORDFORMAT " Steel pieces.\r\n", sexstrings(&opp, HIS, FALSE), opp.gold);
+    else {
+	if (opp.status != MONSTER)
+	    od_printf("%s takes your %" QWORDFORMAT " Steel pieces.\r\n", sexstrings(&opp, HE, TRUE), opp.gold);
+    }
+    winner->gold += opp.gold;
+    loser->gold = 0;
+
+    if (opp.status != MONSTER) {
+	nl();
+	od_set_color(D_GREEN, D_BLACK);
+	if (won) {
+	    od_printf("The Last Words %s Utters Are...\r\n", sexstrings(&tmpuser, HE, FALSE));
+	    nl();
+	    od_printf("\"%s\"\r\n", tmpuser.gaspd);
+	    nl();
+	} else {
+	    od_disp_str("The Last Words You Hear Are...\r\n");
+	    nl();
+	    od_printf("\"%s\"\r\n", tmpuser.winmsg);
+	    nl();
+	}
+	winner->wins++;
+	loser->loses++;
+	SAFECOPY(loser->killer, winner->pseudo);
+	loser->status = DEAD;
+	if (loser->weapon > winner->weapon) {
+	    d = winner->weapon;
+	    winner->weapon = loser->weapon;
+	    loser->weapon = d;
+	    bt = winner->plus;
+	    winner->plus = loser->plus;
+	    loser->plus = bt;
+	    od_set_color(D_GREEN, D_BLACK);
+	    od_printf("%s Hath Taken %s Weapon.\r\n", wstr, lstr);
+	}
+	if (tmpuser.armour > user.armour) {
+	    d = winner->armour;
+	    winner->armour = loser->armour;
+	    loser->armour = d;
+	    od_set_color(L_YELLOW, D_BLACK);
+	    od_printf("%s Hath Taken %s Armour.\r\n", wstr, lstr);
+	}
+	user.attack = weapon[user.weapon].attack;
+	user.power = weapon[user.weapon].power;
+	tmpuser.attack = weapon[tmpuser.weapon].attack;
+	tmpuser.power = weapon[tmpuser.weapon].power;
+	outfile = fopen("data/record.lan", "ab");
+	fprintf(outfile, "%s attacked %s and %s was victorious!\r\n", user.pseudo, tmpuser.pseudo, loser->pseudo);
+	fclose(outfile);
+    }
+    opp.experience *= supplant();
+    winner->experience += opp.experience;
+    if (won || opp.status != MONSTER)
+	od_printf("%s obtain %" QWORDFORMAT " exp points.\r\n", wstr, opp.experience);
+
+    if (opp.status != MONSTER)
+	saveuser(&tmpuser);
+}
+
+void
+findo(void)
+{
+    int             okea;
+    nl();
+    od_set_color(L_YELLOW, D_BLACK);
+    od_disp_str("The Vile Enemy Dropped Something!\r\n");
+    od_disp_str("Do you want to get it? ");
+    if (od_get_answer("YN") == 'Y') {
+	od_disp_str("Yes\r\n");
+	okea = xp_random(99) + 1;
+	if ((okea < 10) && (user.weapon <= 25)) {
+	    user.weapon++;
+	    od_printf("You have found a %s.\r\n", weapon[user.weapon].name);
+	}
+	if ((okea > 11) && (okea < 40)) {
+	    user.gold = user.gold + 40;
+	    od_disp_str("You have come across 40 Steel pieces\r\n");
+	} else
+	    od_disp_str("It's gone!!!!\r\n");
+    } else {
+	od_disp_str("No\r\n");
+	od_disp_str("I wonder what it was?!?\r\n");
+    }
+}
+
+void
+amode(void)
+{
+    double          roll;	       /* Used for To Hit and damage rolls */
+    int             okea;
+    int             tint;
+    roll = tohit(&user, &opp);
+    if (roll < 1.5) {
+	tint = xp_random(3) + 1;
+	switch (tint) {
+	    case 1:
+		od_disp_str("Swish you missed!\r\n");
+		break;
+	    case 2:
+		od_printf("HA HA! %s dodges your swing!\r\n", sexstrings(&opp, HE, FALSE));
+		break;
+	    case 3:
+		od_disp_str("CLANG, The attack is blocked!\r\n");
+		break;
+	    case 4:
+		od_disp_str("You Fight vigorously and miss!\r\n");
+		break;
+	}
+    } else {
+	roll = damage(&user, &opp);
+	if (roll > 5 * user.power)
+	    roll = 5 * user.power;
+	if (roll < 1)
+	    roll = 1;
+	opp.damage += roll;
+	tint = xp_random(2) + 1;
+	switch (tint) {
+	    case 1:
+		od_printf("You sliced %s for %1.0f.\r\n", sexstrings(&opp, HIM, FALSE), roll);
+		break;
+	    case 2:
+		od_printf("You made contact to %s body for %1.0f.\r\n", sexstrings(&opp, HIS, FALSE), roll);
+		break;
+	    case 3:
+		od_printf("You hacked %s for %1.0f.", sexstrings(&opp, HIM, FALSE), roll);
+		break;
+	}
+	if (opp.hps <= opp.damage) {
+	    nl();
+	    tint = xp_random(3) + 1;
+	    switch (tint) {
+		case 1:
+		    od_disp_str("A Painless Death!\r\n");
+		    break;
+		case 2:
+		    od_printf("%s Hath died!\r\n", sexstrings(&opp, HE, TRUE));
+		    break;
+		case 3:
+		    od_disp_str("A Smooth killing!\r\n");
+		    break;
+		case 4:
+		    od_printf("%s has gone to the Abyss!\r\n", sexstrings(&opp, HE, TRUE));
+		    break;
+	    }
+	    okea = xp_random(99) + 1;
+	    if (okea < 30)
+		findo();
+	    endofbattle(TRUE);
+	}
+    }
+}
+
+void
+bmode(void)
+{
+    double          roll;	       /* Used for To Hit and damage rolls */
+    int             tint;
+    if ((opp.hps > opp.damage) && user.damage < user.hps) {
+	roll = tohit(&opp, &user);
+	if (roll < 1.5) {
+	    od_set_color(D_GREEN, D_BLACK);
+	    od_printf("%s attack tears your armour.\r\n", sexstrings(&opp, HIS, TRUE));
+	} else {
+	    roll = tohit(&opp, &user);
+	    if (roll > 5 * opp.power)
+		roll = 5 * opp.power;
+	    if (roll < 1)
+		roll = 1;
+	    tint = xp_random(2) + 1;
+	    switch (tint) {
+		case 1:
+		    od_printf("%s hammered you for %1.0f.\r\n", sexstrings(&opp, HE, TRUE), roll);
+		    break;
+		case 2:
+		    od_printf("%s swung and hit for %1.0f.\r\n", sexstrings(&opp, HE, TRUE), roll);
+		    break;
+		case 3:
+		    od_printf("You are surprised when %s hits you for %1.0f.\r\n", sexstrings(&opp, HE, FALSE), roll);
+		    break;
+	    }
+	    user.damage += roll;
+	    if (user.damage >= user.hps) {
+		nl();
+		tint = xp_random(3) + 1;
+		switch (tint) {
+		    case 1:
+			od_disp_str("Return This Knight To Huma's Breast....\r\n");
+			break;
+		    case 2:
+			od_disp_str("You Hath Been Slain!!\r\n");
+			break;
+		    case 3:
+			od_disp_str("Return Soon Brave Warrior!\r\n");
+			break;
+		    case 4:
+			od_disp_str("May Palidine Be With You!!\r\n");
+			break;
+		}
+		endofbattle(FALSE);
+	    }
+	}
+    }
+}
+
+void
+searcher(char *filename)
+{
+    FILE           *infile;
+    int             a;
+    int             rd;
+    infile = fopen(filename, "rb");
+    user.fights--;
+    rd = xp_random(readnumb(0, infile) - 1) + 1;
+    endofline(infile);
+    for (a = 1; a <= rd; a++) {
+	readline(opp.pseudo, sizeof(opp.pseudo), infile);
+	opp.hps = readnumb(10, infile);
+	opp.damage = 0;
+	opp.attack = readnumb(1, infile);
+	opp.power = readnumb(1, infile);
+	opp.armour = readnumb(1, infile);
+	opp.luck = readnumb(1, infile);
+	opp.strength = readnumb(6, infile);
+	opp.dexterity = readnumb(6, infile);
+	opp.gold = readnumb(0, infile);
+	opp.experience = readnumb(0, infile);
+	opp.status = MONSTER;
+	opp.sex = 'I';
+	endofline(infile);
+    }
+    fclose(infile);
+    opp.attack *= supplant();
+    if (opp.attack < 1)
+	opp.attack = 1;
+    opp.power *= supplant();
+    if (opp.power < 1)
+	opp.power = 1;
+    opp.armour *= supplant();
+    if (opp.armour < 1)
+	opp.armour = 1;
+    opp.luck *= supplant();
+    if (opp.luck < 1)
+	opp.luck = 1;
+    opp.strength *= supplant();
+    if (opp.strength < 1)
+	opp.strength = 1;
+    opp.dexterity *= supplant();
+    if (opp.dexterity < 1)
+	opp.dexterity = 1;
+    opp.hps *= supplant();
+    if (opp.hps < 1)
+	opp.hps = 1;
+    opp.vary = supplant();
+}
+
+void
+attackmodes(void)
+{
+    if (opp.dexterity > user.dexterity) {
+	if (user.damage < user.hps && opp.damage < opp.hps)
+	    bmode();
+	if (user.damage < user.hps && opp.damage < opp.hps)
+	    amode();
+    } else if (opp.dexterity < user.dexterity) {
+	if (user.damage < user.hps && opp.damage < opp.hps)
+	    amode();
+	if (user.damage < user.hps && opp.damage < opp.hps)
+	    bmode();
+    } else {
+	if (user.damage < user.hps && opp.damage < opp.hps)
+	    amode();
+	if (user.damage < user.hps && opp.damage < opp.hps)
+	    bmode();
+    }
+}
+
+void
+battle(void)
+{
+    WORD            playerrem;
+    char            option;
+    nl();
+    while (user.damage < user.hps && opp.damage < opp.hps) {
+	playerrem = user.hps - user.damage;
+	nl();
+	od_set_color(L_YELLOW, D_BLACK);
+	od_printf("You are attacked by a %s.\r\n", opp.pseudo);
+	for (option = '?'; option == '?';) {
+	    od_set_color(L_BLUE, D_BLACK);
+	    od_printf("Combat (%u hps): (B,F,S): ", playerrem);
+	    option = od_get_answer("BFS?");
+	    if (option == '?') {
+		od_disp_str("Help\r\n");
+		nl();
+		nl();
+		od_disp_str("(B)attle your opponent.\r\n");
+		od_disp_str("(F)lee from your opponent.\r\n");
+		od_disp_str("(S)tatus check.\r\n");
+		nl();
+	    }
+	}
+	switch (option) {
+	    case 'B':
+		od_disp_str("Battle\r\n");
+		attackmodes();
+		break;
+	    case 'S':
+		od_disp_str("Stats\r\n");
+		statshow();
+		break;
+	    case 'F':
+		od_disp_str("Flee\r\n");
+		if ((xp_random(4) + 1) + user.dexterity > opp.dexterity) {
+		    nl();
+		    od_set_color(D_GREEN, D_BLACK);
+		    od_disp_str("You Ride away on a Silver Dragon.\r\n");
+		    return;
+		}
+		break;
+	}
+    }
+}
+
+void
+fight(char *filename)
+{
+    searcher(filename);
+    battle();
+}
+
+void
+afight(int lev)
+{
+    char            fname[32];
+    if (user.fights == 0) {
+	nl();
+	od_set_color(D_MAGENTA, D_BLACK);
+	od_disp_str("It's Getting Dark Out!\r\n");
+	od_disp_str("Return to the Nearest Inn!\r\n");
+    } else {
+	od_clr_scr();
+	sprintf(fname, "data/junkm%d.lan", lev);
+	fight(fname);
+    }
+}
+
+void
+doggie(void)
+{
+    char            tmphh[3];
+    int             a, i;
+    DWORD           enemy;
+    BOOL            finder;
+    FILE           *infile;
+    char            temp[81];
+    if (user.battles > 0) {
+	nl();
+	infile = fopen("data/characte.lan", "rb");
+	for (finder = FALSE; finder == FALSE;) {
+	    od_clr_scr();
+	    od_set_color(L_YELLOW, D_BLACK);
+	    od_disp_str("Battle Another Hero:\r\n");
+	    od_disp_str("********************\r\n");
+	    i = 3;
+	    a = 1;
+	    fseek(infile, 0, SEEK_SET);
+	    fgets(temp, sizeof(temp), infile);
+	    while (loadnextuser(&opp, infile)) {
+		if (opp.r > user.r - 4) {
+		    nl();
+		    od_set_color(D_MAGENTA, D_BLACK);
+		    od_printf("%2u.  `bright cyan`%.30s%.*s`bright blue`Lev=%-2u  W=%-2" QWORDFORMAT "  L=%-2" QWORDFORMAT "  S=%s `blinking red`%s"
+			      ,a++, opp.pseudo, 30 - strlen(opp.pseudo), dots
+			      ,opp.r, opp.wins, opp.loses
+			      ,((opp.status & DEAD) ? "SLAIN" : "ALIVE"), ((opp.status & ONLINE) ? "ONLINE" : ""));
+		    if (++i >= od_control.user_screen_length)
+			pausescr();
+		    a += 1;
+		}
+	    }
+	    nl();
+	    od_set_color(L_CYAN, D_BLACK);
+	    od_disp_str("Enter the # of your opponent: ");
+	    od_input_str(tmphh, 2, '0', '9');
+	    enemy = strtoul(tmphh, NULL, 10);
+	    if (enemy < 1 || enemy >= a)
+		continue;
+	    fseek(infile, 0, SEEK_SET);
+	    fgets(temp, sizeof(temp), infile);
+	    for (a = 1; a <= enemy;) {
+		if (!loadnextuser(&opp, infile))
+		    opp.status = DEAD;
+		else if (opp.r > user.r - 4)
+		    a++;
+	    }
+	    if ((!stricmp(opp.pseudo, user.pseudo)) || (opp.status == DEAD)) {
+		fclose(infile);
+		return;
+	    }
+	    finder = TRUE;
+	}
+	fclose(infile);
+	opp.status = PLAYER;
+	user.battles--;
+	opp.experience /= 10;
+	nl();
+	od_disp_str("Your opponent screams out:\r\n");
+	od_printf("\"%s\" as battle is joined.\r\n", opp.bcry);
+	nl();
+	finder = FALSE;
+	battle();
+    }
+}
diff --git a/src/doors/dgnlance/combat.h b/src/doors/dgnlance/combat.h
new file mode 100644
index 0000000000000000000000000000000000000000..ff37b18b950f6b87b27b0a1cbc6f7d640ba39deb
--- /dev/null
+++ b/src/doors/dgnlance/combat.h
@@ -0,0 +1,9 @@
+#ifndef _COMBAT_H_
+#define _COMBAT_H_
+
+#include "dgnlnce.h"
+
+void afight(int lev);
+void doggie(void);
+
+#endif
diff --git a/src/doors/dgnlance/dgnlnce.c b/src/doors/dgnlance/dgnlnce.c
index aec02b041cc406384413838e6d7f22ada2974282..c34e77c335503c365bba86d9fa292e29a51ec57a 100644
--- a/src/doors/dgnlance/dgnlnce.c
+++ b/src/doors/dgnlance/dgnlnce.c
@@ -3,180 +3,25 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
-#include "OpenDoor.h"
-
-#define FIGHTS_PER_DAY	10
-#define BATTLES_PER_DAY	3
-#define FLIGHTS_PER_DAY	3
-
-#ifndef INT64
-#ifdef _MSC_VER
-#define INT64	__int64
-#else
-#define INT64	long long int
-#endif
-#endif
-
-#ifndef INT64FORMAT
-#ifdef __BORLANDC__
-#define	INT64FORMAT	"Ld"
-#else
-#ifdef _MSC_VER
-#define INT64FORMAT	"I64d"
-#else
-#define INT64FORMAT		"lld"
-#endif
-#endif
-#endif
-
-#ifndef QWORD
-#ifdef _MSC_VER
-#define QWORD	unsigned _int64
-#else
-#define	QWORD	unsigned long long int
-#endif
-#endif
-
-#ifndef QWORDFORMAT
-#ifdef __BORLANDC__
-#define	QWORDFORMAT	"Lu"
-#else
-#ifdef _MSC_VER
-#define 	QWORDFORMAT	"I64u"
-#else
-#define 	QWORDFORMAT	"llu"
-#endif
-#endif
-#endif
-
-#define DEAD	1<<0
-#define ONLINE	1<<1
-/* Status for opponent != a player */
-
-enum {
-    MONSTER
-    ,PLAYER
-};
-
-enum {
-    HE
-    ,HIS
-    ,HIM
-};
-
-struct playertype {
-    char            name[31];	       /* Name from BBS drop file */
-    char            pseudo[31];	       /* In-game pseudonym */
-    char            killer[31];	       /* Person killed by (if status==DEAD) */
-    char            bcry[61];	       /* Battle Cry */
-    char            winmsg[61];	       /* What you say when you win a battle */
-    char            gaspd[61];	       /* Dying curse */
-    char            laston[11];	       /* Last date one */
-    char            sex;	       /* Characters sex */
-    DWORD           status;	       /* Status alive or dead for player
-				        * records, PLAYER or MONSTER for
-				        * opponent record (record 0) */
-    /* ToDo make configurable */
-    WORD            flights;	       /* Weird thing... may be number of
-				        * times game can be ran per day */
-    WORD            plus;	       /* Weapon Bonus - Not currently Used */
-    WORD            r;		       /* Level */
-    WORD            strength;	       /* Str */
-    WORD            intelligence;      /* Int */
-    WORD            dexterity;	       /* Dex */
-    WORD            constitution;      /* Con */
-    WORD            charisma;	       /* Cha */
-    QWORD           experience;	       /* Exp */
-    WORD            luck;	       /* Luk */
-    WORD            weapon;	       /* Weapon Number */
-    WORD            armour;	       /* Armour Number */
-    WORD            hps;	       /* Hit Points */
-    WORD            damage;	       /* Damage taken so far */
-    QWORD           gold;	       /* Gold on hand */
-    QWORD           bank;	       /* Gold in bank */
-    WORD            attack;	       /* Weapon Attack */
-    WORD            power;	       /* Weapon Power */
-    QWORD           wins;	       /* Wins so far */
-    QWORD           loses;	       /* Losses so far */
-    WORD            battles;	       /* Battles left today */
-    WORD            fights;	       /* Fights left today */
-    /* Players variance... applied to various rolls, Generally, how good the
-     * player is feeling. Is set at start and not modified */
-    double          vary;
-};
-
 
-struct weapon {
-    char            name[31];
-    WORD            attack;
-    WORD            power;
-    DWORD           cost;
-};
-
-
-struct armour {
-    char            name[31];
-    DWORD           cost;
-};
+#include "OpenDoor.h"
 
+#include "xp64.h"
+#include "xpdev.h"
+#include "dgnlnce.h"
+#include "combat.h"
+#include "fileutils.h"
+#include "userfile.h"
+#include "utils.h"
 
 struct playertype player[3];
-/* player[1] is the current user */
-#define user	player[1]
-/* player[0] is the current enemy/temp player */
-#define opp	player[0]
-/* player[2] is the temporary user */
-#define tmpuser player[2]
-
-const char      dots[] = "...............................................";
 /* In these arrays, 0 isn't actually used */
 QWORD           required[29];	       /* Experience required for each level */
 struct weapon   weapon[26];
 struct armour   armour[26];
-char            temp[81];
-FILE           *infile;		       /* Current input file */
-/************************/
-/* Functions from xpdev */
-/************************/
-#define SAFECOPY(dst,src)                               sprintf(dst,"%.*s",(int)sizeof(dst)-1,src)
-#if defined(__unix__)
-#if !defined(stricmp)
-#define stricmp(x,y)            strcasecmp(x,y)
-#define strnicmp(x,y,z)         strncasecmp(x,y,z)
-#endif
-#endif
-
-/****************************************************************************/
-/* Truncates all white-space chars off end of 'str'     (needed by STRERRROR)   */
-/****************************************************************************/
-char           *
-truncsp(char *str)
-{
-    size_t          i, len;
-    i = len = strlen(str);
-
-    while (i && (str[i - 1] == ' ' || str[i - 1] == '\t' || str[i - 1] == '\r' || str[i - 1] == '\n'))
-	i--;
-    if (i != len)
-	str[i] = 0;		       /* truncate */
-    return (str);
-}
 
-int
-xp_random(int n)
-{
-    float           f;
-    static BOOL     initialized;
-    if (!initialized) {
-	srand(time(NULL));	       /* seed random number generator */
-	rand();			       /* throw away first result */
-	initialized = TRUE;
-    }
-    if (n < 2)
-	return (0);
-    f = (float)rand() / (float)RAND_MAX;
-    return ((int)(n * f));
-}
+const char      dots[] = "...............................................";
+char            temp[81];
 /*****************************/
 /* Functions from common.pas */
 /*****************************/
@@ -190,61 +35,10 @@ date(void)
     strftime(retdate, sizeof(retdate), "%m/%d/%y", localtime(&now));
     return (retdate);
 }
-
-void
-pausescr(void)
-{
-    od_set_color(L_CYAN, D_BLACK);
-    od_disp_str("[Pause]");
-    od_set_color(D_GREY, D_BLACK);
-    od_get_key(TRUE);
-    od_disp_str("\010 \010\010 \010\010 \010\010 \010\010 \010\010 \010\010 \010");
-}
-#define nl()	od_disp_str("\r\n");
-
 /********************************/
 /* Functions from original .pas */
 /********************************/
 
-void            quickexit(void);
-BOOL            loadnextuser(struct playertype * plr);
-BOOL            loaduser(char *name, BOOL bbsname, struct playertype * plr);
-void            writenextuser(struct playertype * plr, FILE * outfile);
-
-double
-playerattack(void)
-{
-    return ((user.attack * user.strength * user.dexterity * (xp_random(5) + 1) * user.vary) /
-	    (opp.armour * opp.dexterity * opp.luck * opp.vary));
-}
-
-double
-playerattack2(void)
-{
-    return ((user.power * user.strength * (xp_random(5) + 1) * (xp_random(5) + 1) * user.vary) /
-	    ((opp.armour) * opp.luck * opp.vary));
-}
-
-double
-opponentattack(void)
-{
-    return ((opp.attack * opp.strength * opp.dexterity * (xp_random(5) + 1) * opp.vary) /
-	    (user.armour * user.dexterity * user.luck * user.vary));
-}
-
-double
-opponentattack2(void)
-{
-    return ((opp.power * opp.strength * (xp_random(5) + 1) * (xp_random(5) + 1) * opp.vary) /
-	    ((user.armour) * user.luck * user.vary));
-}
-
-double
-supplant(void)
-{
-    return ((double)(xp_random(40) + 80)) / 100;
-}
-
 void
 depobank(void)
 {
@@ -269,14 +63,6 @@ withdrawbank(void)
     od_printf("You are now carrying %" QWORDFORMAT " Steel pieces.\r\n", user.gold);
 }
 
-char           *
-readline(char *buf, size_t size)
-{
-    fgets(buf, size, infile);
-    truncsp(buf);
-    return (buf);
-}
-
 void
 checkday(void)
 {
@@ -284,10 +70,11 @@ checkday(void)
     DWORD           h, i, j;
     FILE           *outfile;
     BOOL            newday = FALSE;
+    FILE           *infile;
     struct playertype **playerlist = NULL;
     struct playertype **ra;
     infile = fopen("data/date.lan", "r+b");
-    readline(oldy, sizeof(oldy));
+    readline(oldy, sizeof(oldy), infile);
 
     if (strcmp(oldy, date())) {
 	fseek(infile, 0, SEEK_SET);
@@ -304,14 +91,14 @@ checkday(void)
     if (feof(infile))
 	return;
     i = 0;
-    while (loadnextuser(&tmpuser)) {
+    while (loadnextuser(&tmpuser, infile)) {
 	ra = (struct playertype **) realloc(playerlist, sizeof(struct playertype *) * (i + 1));
 	if (ra == NULL)
-	    quickexit();
+	    exit(1);
 	playerlist = ra;
 	playerlist[i] = (struct playertype *) malloc(sizeof(struct playertype));
 	if (playerlist[i] == NULL)
-	    quickexit();
+	    exit(1);
 	*playerlist[i] = tmpuser;
 	if (newday) {
 	    playerlist[i]->battles = BATTLES_PER_DAY;
@@ -334,7 +121,7 @@ checkday(void)
 	}
     }
     outfile = fopen("data/characte.lan", "wb");
-    fprintf(outfile, "%u\n", i);
+    fprintf(outfile, "%lu\n", i);
     for (j = 0; j < i; j++) {
 	writenextuser(playerlist[j], outfile);
 	free(playerlist[j]);
@@ -347,6 +134,7 @@ void
 playerlist(void)
 {
     int             i, a;
+    FILE           *infile;
     checkday();
     od_clr_scr();
     nl();
@@ -357,7 +145,7 @@ playerlist(void)
     fgets(temp, sizeof(temp), infile);
     i = 3;
     a = 1;
-    while (loadnextuser(&tmpuser)) {
+    while (loadnextuser(&tmpuser, infile)) {
 	nl();
 	od_set_color(D_MAGENTA, D_BLACK);
 	od_printf("%2u.  `bright cyan`%.30s%.*s`green`Lev=%-2u  W=%-6" QWORDFORMAT " L=%-6" QWORDFORMAT " S=%s `blinking red`%s"
@@ -371,85 +159,6 @@ playerlist(void)
     fclose(infile);
 }
 
-void
-writenextuser(struct playertype * plr, FILE * outfile)
-{
-    fprintf(outfile, "%s\n", plr->name);
-    fprintf(outfile, "%s\n", plr->pseudo);
-    fprintf(outfile, "%c\n", plr->sex);
-    fprintf(outfile, "%s\n", plr->gaspd);
-    fprintf(outfile, "%s\n", plr->laston);
-    fprintf(outfile, "%u\n", plr->status);
-    if (plr->status == DEAD)
-	fprintf(outfile, "%s\n", plr->killer);
-    fprintf(outfile, "%u %u %u %u %u %u %" QWORDFORMAT " %u %u %u %u %" QWORDFORMAT " %u %" QWORDFORMAT " %" QWORDFORMAT " %" QWORDFORMAT " %u %u %u %1.4f\n",
-	    plr->strength, plr->intelligence,
-	    plr->luck, plr->dexterity, plr->constitution,
-	    plr->charisma, plr->experience,
-	    plr->r, plr->hps, plr->weapon,
-	    plr->armour, plr->gold,
-	    plr->flights, plr->bank, plr->wins, plr->loses,
-	    plr->plus, plr->fights, plr->battles, plr->vary);
-}
-
-void
-saveuser(struct playertype * plr)
-{
-    DWORD           h, i, j;
-    FILE           *outfile;
-    struct playertype **playerlist = NULL;
-    struct playertype **ra;
-    BOOL            saved = FALSE;
-    infile = fopen("data/characte.lan", "rb");
-    fgets(temp, sizeof(temp), infile);
-    i = 0;
-    while (loadnextuser(&tmpuser)) {
-	ra = (struct playertype **) realloc(playerlist, sizeof(plr) * (i + 1));
-	if (ra == NULL)
-	    quickexit();
-	playerlist = ra;
-	playerlist[i] = (struct playertype *) malloc(sizeof(struct playertype));
-	if (playerlist[i] == NULL)
-	    quickexit();
-	if (!stricmp(tmpuser.name, plr->name)) {
-	    *playerlist[i] = *plr;
-	    saved = TRUE;
-	} else
-	    *playerlist[i] = tmpuser;
-	i++;
-    }
-    fclose(infile);
-
-    if (!saved) {
-	ra = (struct playertype **) realloc(playerlist, sizeof(plr) * (i + 1));
-	if (ra == NULL)
-	    quickexit();
-	playerlist = ra;
-	playerlist[i] = (struct playertype *) malloc(sizeof(struct playertype));
-	if (playerlist[i] == NULL)
-	    quickexit();
-	*playerlist[i] = *plr;
-	i++;
-    }
-    for (j = 0; j < (i - 1); j++) {
-	for (h = j + 1; h < i; h++) {
-	    if (playerlist[h]->experience > playerlist[j]->experience) {
-		tmpuser = *playerlist[h];
-		*playerlist[h] = *playerlist[j];
-		*playerlist[j] = tmpuser;
-	    }
-	}
-    }
-    outfile = fopen("data/characte.lan", "wb");
-    fprintf(outfile, "%u\n", i);
-    for (j = 0; j < i; j++) {
-	writenextuser(playerlist[j], outfile);
-	free(playerlist[j]);
-    }
-    free(playerlist);
-    fclose(outfile);
-}
-
 void
 leave(void)
 {
@@ -483,174 +192,6 @@ heal(void)
     od_printf("%u hit points healed.\r\n", opt);
 }
 
-void
-findo(void)
-{
-    int             okea;
-    nl();
-    od_set_color(L_YELLOW, D_BLACK);
-    od_disp_str("The Vile Enemy Dropped Something!\r\n");
-    od_disp_str("Do you want to get it? ");
-    if (od_get_answer("YN") == 'Y') {
-	od_disp_str("Yes\r\n");
-	okea = xp_random(99) + 1;
-	if ((okea < 10) && (user.weapon <= 25)) {
-	    user.weapon++;
-	    od_printf("You have found a %s.\r\n", weapon[user.weapon].name);
-	}
-	if ((okea > 11) && (okea < 40)) {
-	    user.gold = user.gold + 40;
-	    od_disp_str("You have come across 40 Steel pieces\r\n");
-	} else
-	    od_disp_str("It's gone!!!!\r\n");
-    } else {
-	od_disp_str("No\r\n");
-	od_disp_str("I wonder what it was?!?\r\n");
-    }
-}
-
-void            battle(void);
-
-char           *
-sexstrings(struct playertype * plr, int type, BOOL cap)
-{
-    static char     retbuf[16];
-    char            sex;
-    sex = plr->sex;
-    if (plr->charisma < 8)
-	sex = 'I';
-    switch (sex) {
-	case 'M':
-	    switch (type) {
-		case HIS:
-		    SAFECOPY(retbuf, "his");
-		    break;
-		case HE:
-		    SAFECOPY(retbuf, "he");
-		    break;
-		case HIM:
-		    SAFECOPY(retbuf, "him");
-		    break;
-	    }
-	case 'F':
-	    switch (type) {
-		case HIS:
-		    SAFECOPY(retbuf, "her");
-		    break;
-		case HE:
-		    SAFECOPY(retbuf, "she");
-		    break;
-		case HIM:
-		    SAFECOPY(retbuf, "her");
-		    break;
-	    }
-	case 'I':
-	    switch (type) {
-		case HIS:
-		    SAFECOPY(retbuf, "its");
-		    break;
-		case HE:
-		    SAFECOPY(retbuf, "it");
-		    break;
-		case HIM:
-		    SAFECOPY(retbuf, "it");
-		    break;
-	    }
-    }
-    if (cap)
-	retbuf[0] = toupper(retbuf[0]);
-    return (retbuf);
-}
-
-void
-endofbattle(BOOL won)
-{
-    int             bt;
-    int             d;
-    FILE           *outfile;
-    char            lstr[5];
-    char            wstr[5];
-    struct playertype *winner;
-    struct playertype *loser;
-    if (opp.status != MONSTER)
-	loaduser(opp.name, TRUE, &tmpuser);
-    if (won) {
-	winner = &user;
-	loser = &tmpuser;
-	SAFECOPY(lstr, sexstrings(loser, HIS, FALSE));
-	SAFECOPY(wstr, "You");
-    } else {
-	winner = &tmpuser;
-	loser = &user;
-	SAFECOPY(lstr, sexstrings(winner, HIS, FALSE));
-	SAFECOPY(lstr, "your");
-	opp.experience = user.experience / 10;
-    }
-
-    if (opp.status == MONSTER)
-	opp.gold = opp.gold * supplant();
-    nl();
-    if (won)
-	od_printf("You take %s %" QWORDFORMAT " Steel pieces.\r\n", sexstrings(&opp, HIS, FALSE), opp.gold);
-    else {
-	if (opp.status != MONSTER)
-	    od_printf("%s takes your %" QWORDFORMAT " Steel pieces.\r\n", sexstrings(&opp, HE, TRUE), opp.gold);
-    }
-    winner->gold += opp.gold;
-    loser->gold = 0;
-
-    if (opp.status != MONSTER) {
-	nl();
-	od_set_color(D_GREEN, D_BLACK);
-	if (won) {
-	    od_printf("The Last Words %s Utters Are...\r\n", sexstrings(&tmpuser, HE, FALSE));
-	    nl();
-	    od_printf("\"%s\"\r\n", tmpuser.gaspd);
-	    nl();
-	} else {
-	    od_disp_str("The Last Words You Hear Are...\r\n");
-	    nl();
-	    od_printf("\"%s\"\r\n", tmpuser.winmsg);
-	    nl();
-	}
-	winner->wins++;
-	loser->loses++;
-	SAFECOPY(loser->killer, winner->pseudo);
-	loser->status = DEAD;
-	if (loser->weapon > winner->weapon) {
-	    d = winner->weapon;
-	    winner->weapon = loser->weapon;
-	    loser->weapon = d;
-	    bt = winner->plus;
-	    winner->plus = loser->plus;
-	    loser->plus = bt;
-	    od_set_color(D_GREEN, D_BLACK);
-	    od_printf("%s Hath Taken %s Weapon.\r\n", wstr, lstr);
-	}
-	if (tmpuser.armour > user.armour) {
-	    d = winner->armour;
-	    winner->armour = loser->armour;
-	    loser->armour = d;
-	    od_set_color(L_YELLOW, D_BLACK);
-	    od_printf("%s Hath Taken %s Armour.\r\n", wstr, lstr);
-	}
-	user.attack = weapon[user.weapon].attack;
-	user.power = weapon[user.weapon].power;
-	tmpuser.attack = weapon[tmpuser.weapon].attack;
-	tmpuser.power = weapon[tmpuser.weapon].power;
-	outfile = fopen("data/record.lan", "ab");
-	fprintf(outfile, "%s attacked %s and %s was victorious!\r\n", user.pseudo, tmpuser.pseudo, loser->pseudo);
-	fclose(outfile);
-    }
-    opp.experience *= supplant();
-    winner->experience += opp.experience;
-    if (won || opp.status != MONSTER)
-	od_printf("%s obtain %" QWORDFORMAT " exp points.\r\n", wstr, opp.experience);
-
-    if (opp.status != MONSTER)
-	saveuser(&tmpuser);
-}
-
 void
 levelupdate(void)
 {
@@ -683,152 +224,6 @@ levelupdate(void)
 	user.hps = user.hps + (xp_random(5) + 1) + (user.constitution / 4);
     }
 }
-
-void
-quickexit(void)
-{
-    od_disp_str("The Gods of Krynn Disapprove of your actions!\r\n");
-    exit(1);
-}
-
-void
-amode(void)
-{
-    double          roll;	       /* Used for To Hit and damage rolls */
-    int             okea;
-    int             tint;
-    roll = playerattack();
-    if (roll < 1.5) {
-	tint = xp_random(3) + 1;
-	switch (tint) {
-	    case 1:
-		od_disp_str("Swish you missed!\r\n");
-		break;
-	    case 2:
-		od_printf("HA HA! %s dodges your swing!\r\n", sexstrings(&opp, HE, FALSE));
-		break;
-	    case 3:
-		od_disp_str("CLANG, The attack is blocked!\r\n");
-		break;
-	    case 4:
-		od_disp_str("You Fight vigorously and miss!\r\n");
-		break;
-	}
-    } else {
-	roll = playerattack2();
-	if (roll > 5 * user.power)
-	    roll = 5 * user.power;
-	if (roll < 1)
-	    roll = 1;
-	opp.damage += roll;
-	tint = xp_random(2) + 1;
-	switch (tint) {
-	    case 1:
-		od_printf("You sliced %s for %1.0f.\r\n", sexstrings(&opp, HIM, FALSE), roll);
-		break;
-	    case 2:
-		od_printf("You made contact to %s body for %1.0f.\r\n", sexstrings(&opp, HIS, FALSE), roll);
-		break;
-	    case 3:
-		od_printf("You hacked %s for %1.0f.", sexstrings(&opp, HIM, FALSE), roll);
-		break;
-	}
-	if (opp.hps <= opp.damage) {
-	    nl();
-	    tint = xp_random(3) + 1;
-	    switch (tint) {
-		case 1:
-		    od_disp_str("A Painless Death!\r\n");
-		    break;
-		case 2:
-		    od_printf("%s Hath died!\r\n", sexstrings(&opp, HE, TRUE));
-		    break;
-		case 3:
-		    od_disp_str("A Smooth killing!\r\n");
-		    break;
-		case 4:
-		    od_printf("%s has gone to the Abyss!\r\n", sexstrings(&opp, HE, TRUE));
-		    break;
-	    }
-	    okea = xp_random(99) + 1;
-	    if (okea < 30)
-		findo();
-	    endofbattle(TRUE);
-	}
-    }
-}
-
-void
-bmode(void)
-{
-    double          roll;	       /* Used for To Hit and damage rolls */
-    int             tint;
-    if ((opp.hps > opp.damage) && user.damage < user.hps) {
-	roll = opponentattack();
-	if (roll < 1.5) {
-	    od_set_color(D_GREEN, D_BLACK);
-	    od_printf("%s attack tears your armour.\r\n", sexstrings(&opp, HIS, TRUE));
-	} else {
-	    roll = opponentattack2();
-	    if (roll > 5 * opp.power)
-		roll = 5 * opp.power;
-	    if (roll < 1)
-		roll = 1;
-	    tint = xp_random(2) + 1;
-	    switch (tint) {
-		case 1:
-		    od_printf("%s hammered you for %1.0f.\r\n", sexstrings(&opp, HE, TRUE), roll);
-		    break;
-		case 2:
-		    od_printf("%s swung and hit for %1.0f.\r\n", sexstrings(&opp, HE, TRUE), roll);
-		    break;
-		case 3:
-		    od_printf("You are surprised when %s hits you for %1.0f.\r\n", sexstrings(&opp, HE, FALSE), roll);
-		    break;
-	    }
-	    user.damage += roll;
-	    if (user.damage >= user.hps) {
-		nl();
-		tint = xp_random(3) + 1;
-		switch (tint) {
-		    case 1:
-			od_disp_str("Return This Knight To Huma's Breast....\r\n");
-			break;
-		    case 2:
-			od_disp_str("You Hath Been Slain!!\r\n");
-			break;
-		    case 3:
-			od_disp_str("Return Soon Brave Warrior!\r\n");
-			break;
-		    case 4:
-			od_disp_str("May Palidine Be With You!!\r\n");
-			break;
-		}
-		endofbattle(FALSE);
-	    }
-	}
-    }
-}
-
-void
-statshow(void)
-{
-    od_clr_scr();
-    od_set_color(D_MAGENTA, D_BLACK);
-    od_printf("Name: %s   Level: %d\r\n", user.pseudo, user.r);
-    od_set_color(L_CYAN, D_BLACK);
-    od_printf("W/L: %" QWORDFORMAT "/%" QWORDFORMAT "   Exp: %" QWORDFORMAT "\r\n", user.wins, user.loses, user.experience);
-    nl();
-    od_set_color(L_YELLOW, D_BLACK);
-    od_printf("Steel  (in hand): %" QWORDFORMAT "\r\n", user.gold);
-    od_printf("Steel  (in bank): %" QWORDFORMAT "\r\n", user.bank);
-    nl();
-    od_set_color(L_BLUE, D_BLACK);
-    od_printf("Battles: %u   Retreats: %u    Fights: %u   Hps: %u(%u)\r\n", user.battles, user.flights, user.fights, user.hps - user.damage, user.hps);
-    nl();
-    od_set_color(L_CYAN, D_BLACK);
-    od_printf("Weapon: %s     Armor: %s\r\n", weapon[user.weapon].name, armour[user.armour].name);
-}
 BOOL
 incre(void)
 {
@@ -986,266 +381,6 @@ chstats(void)
     }
 }
 
-void
-attackmodes(void)
-{
-    if (opp.dexterity > user.dexterity) {
-	if (user.damage < user.hps && opp.damage < opp.hps)
-	    bmode();
-	if (user.damage < user.hps && opp.damage < opp.hps)
-	    amode();
-    } else if (opp.dexterity < user.dexterity) {
-	if (user.damage < user.hps && opp.damage < opp.hps)
-	    amode();
-	if (user.damage < user.hps && opp.damage < opp.hps)
-	    bmode();
-    } else {
-	if (user.damage < user.hps && opp.damage < opp.hps)
-	    amode();
-	if (user.damage < user.hps && opp.damage < opp.hps)
-	    bmode();
-    }
-}
-
-double
-readfloat(float deflt)
-{
-    char            buf[101];
-    int             pos = 0;
-    int             rd;
-    double          ret;
-    buf[0] = 0;
-    while ((rd = fgetc(infile)) != EOF) {
-	if (rd == '\r')
-	    continue;
-	if (rd == '\n') {
-	    ungetc('\n', infile);
-	    break;
-	}
-	/* Skip leading spaces */
-	if (!pos && isspace(rd))
-	    continue;
-	if (isspace(rd))
-	    break;
-	buf[pos++] = rd;
-    }
-    if (!pos)
-	return (deflt);
-    buf[pos++] = 0;
-    ret = strtod(buf, NULL);
-    return (ret);
-}
-
-QWORD
-readnumb(QWORD deflt)
-{
-    char            buf[101];
-    int             pos = 0;
-    int             rd;
-    QWORD           ret;
-    buf[0] = 0;
-
-    while ((rd = fgetc(infile)) != EOF) {
-	if (rd == '\r')
-	    continue;
-	if (rd == '\n') {
-	    ungetc('\n', infile);
-	    break;
-	}
-	/* Skip leading spaces */
-	if (!pos && isspace(rd))
-	    continue;
-	if (isspace(rd))
-	    break;
-	buf[pos++] = rd;
-    }
-    if (!pos)
-	return (deflt);
-    buf[pos++] = 0;
-    ret = strtoull(buf, NULL, 10);
-    return (ret);
-}
-
-void
-endofline(void)
-{
-    int             rd;
-    while ((rd = fgetc(infile)) != EOF) {
-	if (rd == '\n');
-	break;
-    }
-}
-
-void
-searcher(void)
-{
-    int             a;
-    int             rd;
-    user.fights--;
-    rd = xp_random(readnumb(0) - 1) + 1;
-    endofline();
-    for (a = 1; a <= rd; a++) {
-	readline(opp.pseudo, sizeof(opp.pseudo));
-	opp.hps = readnumb(10);
-	opp.damage = 0;
-	opp.attack = readnumb(1);
-	opp.power = readnumb(1);
-	opp.armour = readnumb(1);
-	opp.luck = readnumb(1);
-	opp.strength = readnumb(6);
-	opp.dexterity = readnumb(6);
-	opp.gold = readnumb(0);
-	opp.experience = readnumb(0);
-	opp.status = MONSTER;
-	opp.sex = 'I';
-	endofline();
-    }
-    fclose(infile);
-    opp.attack *= supplant();
-    if (opp.attack < 1)
-	opp.attack = 1;
-    opp.power *= supplant();
-    if (opp.power < 1)
-	opp.power = 1;
-    opp.armour *= supplant();
-    if (opp.armour < 1)
-	opp.armour = 1;
-    opp.luck *= supplant();
-    if (opp.luck < 1)
-	opp.luck = 1;
-    opp.strength *= supplant();
-    if (opp.strength < 1)
-	opp.strength = 1;
-    opp.dexterity *= supplant();
-    if (opp.dexterity < 1)
-	opp.dexterity = 1;
-    opp.hps *= supplant();
-    if (opp.hps < 1)
-	opp.hps = 1;
-    opp.vary = supplant();
-}
-
-void
-fight(char *filename)
-{
-    infile = fopen(filename, "rb");
-    searcher();
-    battle();
-}
-
-void
-doggie(void)
-{
-    char            tmphh[3];
-    int             a, i;
-    DWORD           enemy;
-    BOOL            finder;
-    if (user.battles > 0) {
-	nl();
-	infile = fopen("data/characte.lan", "rb");
-	for (finder = FALSE; finder == FALSE;) {
-	    od_clr_scr();
-	    od_set_color(L_YELLOW, D_BLACK);
-	    od_disp_str("Battle Another Hero:\r\n");
-	    od_disp_str("********************\r\n");
-	    i = 3;
-	    a = 1;
-	    fseek(infile, 0, SEEK_SET);
-	    fgets(temp, sizeof(temp), infile);
-	    while (loadnextuser(&opp)) {
-		if (opp.r > user.r - 4) {
-		    nl();
-		    od_set_color(D_MAGENTA, D_BLACK);
-		    od_printf("%2u.  `bright cyan`%.30s%.*s`bright blue`Lev=%-2u  W=%-2" QWORDFORMAT "  L=%-2" QWORDFORMAT "  S=%s `blinking red`%s"
-			      ,a++, opp.pseudo, 30 - strlen(opp.pseudo), dots
-			      ,opp.r, opp.wins, opp.loses
-			      ,((opp.status & DEAD) ? "SLAIN" : "ALIVE"), ((opp.status & ONLINE) ? "ONLINE" : ""));
-		    if (++i >= od_control.user_screen_length)
-			pausescr();
-		    a += 1;
-		}
-	    }
-	    nl();
-	    od_set_color(L_CYAN, D_BLACK);
-	    od_disp_str("Enter the # of your opponent: ");
-	    od_input_str(tmphh, 2, '0', '9');
-	    enemy = strtoul(tmphh, NULL, 10);
-	    if (enemy < 1 || enemy >= a)
-		continue;
-	    fseek(infile, 0, SEEK_SET);
-	    fgets(temp, sizeof(temp), infile);
-	    for (a = 1; a <= enemy;) {
-		if (!loadnextuser(&opp))
-		    opp.status = DEAD;
-		else if (opp.r > user.r - 4)
-		    a++;
-	    }
-	    if ((!stricmp(opp.pseudo, user.pseudo)) || (opp.status == DEAD)) {
-		fclose(infile);
-		return;
-	    }
-	    finder = TRUE;
-	}
-	fclose(infile);
-	opp.status = PLAYER;
-	user.battles--;
-	opp.experience /= 10;
-	nl();
-	od_disp_str("Your opponent screams out:\r\n");
-	od_printf("\"%s\" as battle is joined.\r\n", opp.bcry);
-	nl();
-	finder = FALSE;
-	battle();
-    }
-}
-
-void
-battle(void)
-{
-    WORD            playerrem;
-    char            option;
-    nl();
-    while (user.damage < user.hps && opp.damage < opp.hps) {
-	playerrem = user.hps - user.damage;
-	nl();
-	od_set_color(L_YELLOW, D_BLACK);
-	od_printf("You are attacked by a %s.\r\n", opp.pseudo);
-	for (option = '?'; option == '?';) {
-	    od_set_color(L_BLUE, D_BLACK);
-	    od_printf("Combat (%u hps): (B,F,S): ", playerrem);
-	    option = od_get_answer("BFS?");
-	    if (option == '?') {
-		od_disp_str("Help\r\n");
-		nl();
-		nl();
-		od_disp_str("(B)attle your opponent.\r\n");
-		od_disp_str("(F)lee from your opponent.\r\n");
-		od_disp_str("(S)tatus check.\r\n");
-		nl();
-	    }
-	}
-	switch (option) {
-	    case 'B':
-		od_disp_str("Battle\r\n");
-		attackmodes();
-		break;
-	    case 'S':
-		od_disp_str("Stats\r\n");
-		statshow();
-		break;
-	    case 'F':
-		od_disp_str("Flee\r\n");
-		if ((xp_random(4) + 1) + user.dexterity > opp.dexterity) {
-		    nl();
-		    od_set_color(D_GREEN, D_BLACK);
-		    od_disp_str("You Ride away on a Silver Dragon.\r\n");
-		    return;
-		}
-		break;
-	}
-    }
-}
-
 void
 credits(void)
 {
@@ -1584,22 +719,6 @@ gamble(void)
     }
 }
 
-void
-afight(int lev)
-{
-    char            fname[32];
-    if (user.fights == 0) {
-	nl();
-	od_set_color(D_MAGENTA, D_BLACK);
-	od_disp_str("It's Getting Dark Out!\r\n");
-	od_disp_str("Return to the Nearest Inn!\r\n");
-    } else {
-	od_clr_scr();
-	sprintf(fname, "data/junkm%d.lan", lev);
-	fight(fname);
-    }
-}
-
 void
 bulletin(void)
 {
@@ -1740,86 +859,13 @@ menuit(void)
     od_clr_scr();
     od_send_file("text/menu");
 }
-BOOL
-loadnextuser(struct playertype * plr)
-{
-    if (feof(infile))
-	return (FALSE);
-    readline(plr->name, sizeof(plr->name));
-    if (feof(infile))
-	return (FALSE);
-    readline(plr->pseudo, sizeof(plr->pseudo));
-    if (feof(infile))
-	return (FALSE);
-    fread(&plr->sex, 1, 1, infile);
-    endofline();
-    if (feof(infile))
-	return (FALSE);
-    readline(plr->gaspd, sizeof(plr->gaspd));
-    if (feof(infile))
-	return (FALSE);
-    readline(plr->laston, sizeof(plr->laston));
-    if (feof(infile))
-	return (FALSE);
-    fgets(temp, sizeof(temp), infile);
-    plr->status = strtoul(temp, NULL, 10);
-    if (feof(infile))
-	return (FALSE);
-    if (plr->status == DEAD) {
-	readline(plr->killer, sizeof(plr->killer));
-	if (feof(infile))
-	    return (FALSE);
-    }
-    plr->strength = readnumb(6);
-    plr->intelligence = readnumb(6);
-    plr->luck = readnumb(6);
-    plr->dexterity = readnumb(6);
-    plr->constitution = readnumb(6);
-    plr->charisma = readnumb(6);
-    plr->experience = readnumb(0);
-    plr->r = readnumb(1);
-    plr->hps = readnumb(10);
-    plr->weapon = readnumb(1);
-    plr->armour = readnumb(1);
-    plr->gold = readnumb(0);
-    plr->flights = readnumb(3);
-    plr->bank = readnumb(0);
-    plr->wins = readnumb(0);
-    plr->loses = readnumb(0);
-    plr->plus = readnumb(0);
-    plr->fights = readnumb(FIGHTS_PER_DAY);
-    plr->battles = readnumb(BATTLES_PER_DAY);
-    plr->vary = readfloat(supplant());
-    endofline();
-    return (TRUE);
-}
-BOOL
-loaduser(char *name, BOOL bbsname, struct playertype * plr)
-{
-    infile = fopen("data/characte.lan", "rb");
-    fgets(temp, sizeof(temp), infile);
-    while (loadnextuser(plr)) {
-	if (bbsname) {
-	    if (!stricmp(plr->name, name)) {
-		fclose(infile);
-		return (TRUE);
-	    }
-	} else {
-	    if (!stricmp(plr->pseudo, name)) {
-		fclose(infile);
-		return (TRUE);
-	    }
-	}
-    }
-    fclose(infile);
-    return (FALSE);
-}
 
 int
 main(int argc, char **argv)
 {
     DWORD           i;
     BOOL            found;
+    FILE           *infile;
     od_init();
     checkday();
     atexit(leave);
@@ -1867,30 +913,30 @@ main(int argc, char **argv)
     infile = fopen("data/weapons.lan", "rb");
     od_set_color(L_BLUE, D_BLACK);
     for (i = 1; i <= 25; i++) {
-	readline(weapon[i].name, sizeof(weapon[i].name));
-	weapon[i].attack = readnumb(1);
-	weapon[i].power = readnumb(1);
-	endofline();
+	readline(weapon[i].name, sizeof(weapon[i].name), infile);
+	weapon[i].attack = readnumb(1, infile);
+	weapon[i].power = readnumb(1, infile);
+	endofline(infile);
     }
     fclose(infile);
     infile = fopen("data/armor.lan", "rb");
     od_set_color(L_BLUE, D_BLACK);
     for (i = 1; i <= 25; i++)
-	readline(armour[i].name, sizeof(armour[i].name));
+	readline(armour[i].name, sizeof(armour[i].name), infile);
     fclose(infile);
     infile = fopen("data/prices.lan", "rb");
     for (i = 1; i <= 25; i++) {
-	weapon[i].cost = readnumb(100000000);
+	weapon[i].cost = readnumb(100000000, infile);
 	armour[i].cost = weapon[i].cost;
-	endofline();
+	endofline(infile);
     }
     fclose(infile);
     user.attack = weapon[user.weapon].attack;
     user.power = weapon[user.weapon].power;
     infile = fopen("data/experience.lan", "rb");
     for (i = 1; i <= 28; i++) {
-	required[i] = readnumb(100000000);
-	endofline();
+	required[i] = readnumb(100000000, infile);
+	endofline(infile);
     }
     fclose(infile);
     od_set_color(L_YELLOW, D_BLACK);
diff --git a/src/doors/dgnlance/dgnlnce.h b/src/doors/dgnlance/dgnlnce.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a0ba6fec66e58295161c7ae940d1d7e8781ad76
--- /dev/null
+++ b/src/doors/dgnlance/dgnlnce.h
@@ -0,0 +1,101 @@
+#ifndef _DGNLNCE_H_
+#define _DGNLNCE_H_
+
+#include <stdio.h>
+
+#include "xp64.h"
+#include "OpenDoor.h"
+
+#define FIGHTS_PER_DAY	10
+#define BATTLES_PER_DAY	3
+#define FLIGHTS_PER_DAY	3
+
+#define DEAD	1<<0
+#define ONLINE	1<<1
+
+/* Status for opponent */
+enum {
+    MONSTER
+    ,PLAYER
+};
+
+/* Used for sextrings() */
+enum {
+    HE
+    ,HIS
+    ,HIM
+};
+
+struct playertype {
+    char            name[31];	       /* Name from BBS drop file */
+    char            pseudo[31];	       /* In-game pseudonym */
+    char            killer[31];	       /* Person killed by (if status==DEAD) */
+    char            bcry[61];	       /* Battle Cry */
+    char            winmsg[61];	       /* What you say when you win a battle */
+    char            gaspd[61];	       /* Dying curse */
+    char            laston[11];	       /* Last date one */
+    char            sex;	       /* Characters sex */
+    DWORD           status;	       /* Status alive or dead for player
+				        * records, PLAYER or MONSTER for
+				        * opponent record (record 0) */
+    /* ToDo make configurable */
+    WORD            flights;	       /* Weird thing... may be number of
+				        * times game can be ran per day */
+    WORD            plus;	       /* Weapon Bonus - Not currently Used */
+    WORD            r;		       /* Level */
+    WORD            strength;	       /* Str */
+    WORD            intelligence;      /* Int */
+    WORD            dexterity;	       /* Dex */
+    WORD            constitution;      /* Con */
+    WORD            charisma;	       /* Cha */
+    QWORD           experience;	       /* Exp */
+    WORD            luck;	       /* Luk */
+    WORD            weapon;	       /* Weapon Number */
+    WORD            armour;	       /* Armour Number */
+    WORD            hps;	       /* Hit Points */
+    WORD            damage;	       /* Damage taken so far */
+    QWORD           gold;	       /* Gold on hand */
+    QWORD           bank;	       /* Gold in bank */
+    WORD            attack;	       /* Weapon Attack */
+    WORD            power;	       /* Weapon Power */
+    QWORD           wins;	       /* Wins so far */
+    QWORD           loses;	       /* Losses so far */
+    WORD            battles;	       /* Battles left today */
+    WORD            fights;	       /* Fights left today */
+    /* Players variance... applied to various rolls, Generally, how good the
+     * player is feeling. Is set at start and not modified */
+    double          vary;
+};
+
+struct weapon {
+    char            name[31];
+    WORD            attack;
+    WORD            power;
+    DWORD           cost;
+};
+
+struct armour {
+    char            name[31];
+    DWORD           cost;
+};
+
+
+extern struct playertype player[3];
+/* player[1] is the current user */
+#define user	player[1]
+/* player[0] is the current enemy */
+#define opp	player[0]
+/* player[2] is the temporary user */
+#define tmpuser player[2]
+
+/* In these arrays, 0 isn't actually used */
+extern QWORD           required[29];	       /* Experience required for each level */
+extern struct weapon   weapon[26];
+extern struct armour   armour[26];
+extern const char	dots[];
+FILE           *infile;		       /* Current input file */
+
+/* Utility macros */
+#define nl()	od_disp_str("\r\n");
+
+#endif
diff --git a/src/doors/dgnlance/fileutils.c b/src/doors/dgnlance/fileutils.c
new file mode 100644
index 0000000000000000000000000000000000000000..7adbb7a8fe51670eb6384355fe2be302457bba8c
--- /dev/null
+++ b/src/doors/dgnlance/fileutils.c
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "xpdev.h"		       /* truncsp() */
+#include "fileutils.h"
+
+char           *
+readline(char *buf, size_t size, FILE * infile)
+{
+    fgets(buf, size, infile);
+    truncsp(buf);
+    return (buf);
+}
+
+double
+readfloat(float deflt, FILE * infile)
+{
+    char            buf[101];
+    int             pos = 0;
+    int             rd;
+    double          ret;
+    buf[0] = 0;
+    while ((rd = fgetc(infile)) != EOF) {
+	if (rd == '\r')
+	    continue;
+	if (rd == '\n') {
+	    ungetc('\n', infile);
+	    break;
+	}
+	/* Skip leading spaces */
+	if (!pos && isspace(rd))
+	    continue;
+	if (isspace(rd))
+	    break;
+	buf[pos++] = rd;
+    }
+    if (!pos)
+	return (deflt);
+    buf[pos++] = 0;
+    ret = strtod(buf, NULL);
+    return (ret);
+}
+
+QWORD
+readnumb(QWORD deflt, FILE * infile)
+{
+    char            buf[101];
+    int             pos = 0;
+    int             rd;
+    QWORD           ret;
+    buf[0] = 0;
+
+    while ((rd = fgetc(infile)) != EOF) {
+	if (rd == '\r')
+	    continue;
+	if (rd == '\n') {
+	    ungetc('\n', infile);
+	    break;
+	}
+	/* Skip leading spaces */
+	if (!pos && isspace(rd))
+	    continue;
+	if (isspace(rd))
+	    break;
+	buf[pos++] = rd;
+    }
+    if (!pos)
+	return (deflt);
+    buf[pos++] = 0;
+    ret = strtoull(buf, NULL, 10);
+    return (ret);
+}
+
+void
+endofline(FILE * infile)
+{
+    int             rd;
+    while ((rd = fgetc(infile)) != EOF) {
+	if (rd == '\n');
+	break;
+    }
+}
diff --git a/src/doors/dgnlance/fileutils.h b/src/doors/dgnlance/fileutils.h
new file mode 100644
index 0000000000000000000000000000000000000000..3c116de6b61cfce6e72c90a519b7ae652290f89b
--- /dev/null
+++ b/src/doors/dgnlance/fileutils.h
@@ -0,0 +1,11 @@
+#ifndef _FILEUTILS_H_
+#define _FILEUTILS_H_
+
+#include "xp64.h"
+
+char *readline(char *buf, size_t size, FILE *infile);
+void endofline(FILE *infile);
+QWORD readnumb(QWORD deflt, FILE *infile);
+double readfloat(float deflt, FILE *infile);
+
+#endif
\ No newline at end of file
diff --git a/src/doors/dgnlance/objects.mk b/src/doors/dgnlance/objects.mk
index ea8449242ba1dd793b4b1ebf143a8bcf86945ccd..40e4a48255fc35342b0eddba009d3043e2236125 100644
--- a/src/doors/dgnlance/objects.mk
+++ b/src/doors/dgnlance/objects.mk
@@ -1 +1,6 @@
-OBJS	=	$(OBJODIR)$(DIRSEP)dgnlnce$(OFILE)
+OBJS	=	$(OBJODIR)$(DIRSEP)dgnlnce$(OFILE) \
+		$(OBJODIR)$(DIRSEP)xpdev$(OFILE) \
+		$(OBJODIR)$(DIRSEP)userfile$(OFILE) \
+		$(OBJODIR)$(DIRSEP)fileutils$(OFILE) \
+		$(OBJODIR)$(DIRSEP)utils$(OFILE) \
+		$(OBJODIR)$(DIRSEP)combat$(OFILE)
diff --git a/src/doors/dgnlance/userfile.c b/src/doors/dgnlance/userfile.c
new file mode 100644
index 0000000000000000000000000000000000000000..04395b2b31e72609913a2d6519003704fb7cca04
--- /dev/null
+++ b/src/doors/dgnlance/userfile.c
@@ -0,0 +1,169 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "fileutils.h"
+#include "xpdev.h"
+#include "dgnlnce.h"
+#include "utils.h"
+
+BOOL
+loadnextuser(struct playertype * plr, FILE * infile)
+{
+    char            temp[81];
+    if (feof(infile))
+	return (FALSE);
+    readline(plr->name, sizeof(plr->name), infile);
+    if (feof(infile))
+	return (FALSE);
+    readline(plr->pseudo, sizeof(plr->pseudo), infile);
+    if (feof(infile))
+	return (FALSE);
+    fread(&plr->sex, 1, 1, infile);
+    endofline(infile);
+    if (feof(infile))
+	return (FALSE);
+    readline(plr->gaspd, sizeof(plr->gaspd), infile);
+    if (feof(infile))
+	return (FALSE);
+    readline(plr->laston, sizeof(plr->laston), infile);
+    if (feof(infile))
+	return (FALSE);
+    fgets(temp, sizeof(temp), infile);
+    plr->status = strtoul(temp, NULL, 10);
+    if (feof(infile))
+	return (FALSE);
+    if (plr->status == DEAD) {
+	readline(plr->killer, sizeof(plr->killer), infile);
+	if (feof(infile))
+	    return (FALSE);
+    }
+    plr->strength = readnumb(6, infile);
+    plr->intelligence = readnumb(6, infile);
+    plr->luck = readnumb(6, infile);
+    plr->dexterity = readnumb(6, infile);
+    plr->constitution = readnumb(6, infile);
+    plr->charisma = readnumb(6, infile);
+    plr->experience = readnumb(0, infile);
+    plr->r = readnumb(1, infile);
+    plr->hps = readnumb(10, infile);
+    plr->weapon = readnumb(1, infile);
+    plr->armour = readnumb(1, infile);
+    plr->gold = readnumb(0, infile);
+    plr->flights = readnumb(3, infile);
+    plr->bank = readnumb(0, infile);
+    plr->wins = readnumb(0, infile);
+    plr->loses = readnumb(0, infile);
+    plr->plus = readnumb(0, infile);
+    plr->fights = readnumb(FIGHTS_PER_DAY, infile);
+    plr->battles = readnumb(BATTLES_PER_DAY, infile);
+    plr->vary = readfloat(supplant(), infile);
+    endofline(infile);
+    return (TRUE);
+}
+BOOL
+loaduser(char *name, BOOL bbsname, struct playertype * plr)
+{
+    char            temp[81];
+    FILE           *infile;
+    infile = fopen("data/characte.lan", "rb");
+    fgets(temp, sizeof(temp), infile);
+    while (loadnextuser(plr, infile)) {
+	if (bbsname) {
+	    if (!stricmp(plr->name, name)) {
+		fclose(infile);
+		return (TRUE);
+	    }
+	} else {
+	    if (!stricmp(plr->pseudo, name)) {
+		fclose(infile);
+		return (TRUE);
+	    }
+	}
+    }
+    fclose(infile);
+    return (FALSE);
+}
+
+void
+writenextuser(struct playertype * plr, FILE * outfile)
+{
+    fprintf(outfile, "%s\n", plr->name);
+    fprintf(outfile, "%s\n", plr->pseudo);
+    fprintf(outfile, "%c\n", plr->sex);
+    fprintf(outfile, "%s\n", plr->gaspd);
+    fprintf(outfile, "%s\n", plr->laston);
+    fprintf(outfile, "%lu\n", plr->status);
+    if (plr->status == DEAD)
+	fprintf(outfile, "%s\n", plr->killer);
+    fprintf(outfile, "%u %u %u %u %u %u %" QWORDFORMAT " %u %u %u %u %" QWORDFORMAT " %u %" QWORDFORMAT " %" QWORDFORMAT " %" QWORDFORMAT " %u %u %u %1.4f\n",
+	    plr->strength, plr->intelligence,
+	    plr->luck, plr->dexterity, plr->constitution,
+	    plr->charisma, plr->experience,
+	    plr->r, plr->hps, plr->weapon,
+	    plr->armour, plr->gold,
+	    plr->flights, plr->bank, plr->wins, plr->loses,
+	    plr->plus, plr->fights, plr->battles, plr->vary);
+}
+
+void
+saveuser(struct playertype * plr)
+{
+    DWORD           h, i, j;
+    FILE           *outfile;
+    FILE           *infile;
+    char            temp[81];
+
+    struct playertype **playerlist = NULL;
+    struct playertype **ra;
+    BOOL            saved = FALSE;
+    infile = fopen("data/characte.lan", "rb");
+    fgets(temp, sizeof(temp), infile);
+    i = 0;
+    while (loadnextuser(&tmpuser, infile)) {
+	ra = (struct playertype **) realloc(playerlist, sizeof(plr) * (i + 1));
+	if (ra == NULL)
+	    exit(1);;
+	playerlist = ra;
+	playerlist[i] = (struct playertype *) malloc(sizeof(struct playertype));
+	if (playerlist[i] == NULL)
+	    exit(1);;
+	if (!stricmp(tmpuser.name, plr->name)) {
+	    *playerlist[i] = *plr;
+	    saved = TRUE;
+	} else
+	    *playerlist[i] = tmpuser;
+	i++;
+    }
+    fclose(infile);
+
+    if (!saved) {
+	ra = (struct playertype **) realloc(playerlist, sizeof(plr) * (i + 1));
+	if (ra == NULL)
+	    exit(1);;
+	playerlist = ra;
+	playerlist[i] = (struct playertype *) malloc(sizeof(struct playertype));
+	if (playerlist[i] == NULL)
+	    exit(1);;
+	*playerlist[i] = *plr;
+	i++;
+    }
+    for (j = 0; j < (i - 1); j++) {
+	for (h = j + 1; h < i; h++) {
+	    if (playerlist[h]->experience > playerlist[j]->experience) {
+		tmpuser = *playerlist[h];
+		*playerlist[h] = *playerlist[j];
+		*playerlist[j] = tmpuser;
+	    }
+	}
+    }
+    outfile = fopen("data/characte.lan", "wb");
+    fprintf(outfile, "%lu\n", i);
+    for (j = 0; j < i; j++) {
+	writenextuser(playerlist[j], outfile);
+	free(playerlist[j]);
+    }
+    free(playerlist);
+    fclose(outfile);
+}
diff --git a/src/doors/dgnlance/userfile.h b/src/doors/dgnlance/userfile.h
new file mode 100644
index 0000000000000000000000000000000000000000..f77672f678db2b1081ce6807fa0737dd98018207
--- /dev/null
+++ b/src/doors/dgnlance/userfile.h
@@ -0,0 +1,12 @@
+#ifndef _USERFILE_H_
+#define _USERFILE_H_
+
+#include "OpenDoor.h"	/* BOOL */
+#include "dgnlnce.h"	/* struct playertype */
+
+void writenextuser(struct playertype * plr, FILE * outfile);
+void saveuser(struct playertype * plr);
+BOOL loadnextuser(struct playertype * plr, FILE *infile);
+BOOL loaduser(char *name, BOOL bbsname, struct playertype * plr);
+
+#endif
diff --git a/src/doors/dgnlance/utils.c b/src/doors/dgnlance/utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..9ac6ba5db321f200519f03081baa362764da6af2
--- /dev/null
+++ b/src/doors/dgnlance/utils.c
@@ -0,0 +1,94 @@
+#include <ctype.h>
+
+#include "OpenDoor.h"
+
+#include "dgnlnce.h"
+#include "xp64.h"
+#include "xpdev.h"
+
+double
+supplant(void)
+{
+    return ((double)(xp_random(40) + 80)) / 100;
+}
+
+void
+statshow(void)
+{
+    od_clr_scr();
+    od_set_color(D_MAGENTA, D_BLACK);
+    od_printf("Name: %s   Level: %d\r\n", user.pseudo, user.r);
+    od_set_color(L_CYAN, D_BLACK);
+    od_printf("W/L: %" QWORDFORMAT "/%" QWORDFORMAT "   Exp: %" QWORDFORMAT "\r\n", user.wins, user.loses, user.experience);
+    nl();
+    od_set_color(L_YELLOW, D_BLACK);
+    od_printf("Steel  (in hand): %" QWORDFORMAT "\r\n", user.gold);
+    od_printf("Steel  (in bank): %" QWORDFORMAT "\r\n", user.bank);
+    nl();
+    od_set_color(L_BLUE, D_BLACK);
+    od_printf("Battles: %u   Retreats: %u    Fights: %u   Hps: %u(%u)\r\n", user.battles, user.flights, user.fights, user.hps - user.damage, user.hps);
+    nl();
+    od_set_color(L_CYAN, D_BLACK);
+    od_printf("Weapon: %s     Armor: %s\r\n", weapon[user.weapon].name, armour[user.armour].name);
+}
+
+void
+pausescr(void)
+{
+    od_set_color(L_CYAN, D_BLACK);
+    od_disp_str("[Pause]");
+    od_set_color(D_GREY, D_BLACK);
+    od_get_key(TRUE);
+    od_disp_str("\010 \010\010 \010\010 \010\010 \010\010 \010\010 \010\010 \010");
+}
+
+char           *
+sexstrings(struct playertype * plr, int type, BOOL cap)
+{
+    static char     retbuf[16];
+    char            sex;
+    sex = plr->sex;
+    if (plr->charisma < 8)
+	sex = 'I';
+    switch (sex) {
+	case 'M':
+	    switch (type) {
+		case HIS:
+		    SAFECOPY(retbuf, "his");
+		    break;
+		case HE:
+		    SAFECOPY(retbuf, "he");
+		    break;
+		case HIM:
+		    SAFECOPY(retbuf, "him");
+		    break;
+	    }
+	case 'F':
+	    switch (type) {
+		case HIS:
+		    SAFECOPY(retbuf, "her");
+		    break;
+		case HE:
+		    SAFECOPY(retbuf, "she");
+		    break;
+		case HIM:
+		    SAFECOPY(retbuf, "her");
+		    break;
+	    }
+	case 'I':
+	    switch (type) {
+		case HIS:
+		    SAFECOPY(retbuf, "its");
+		    break;
+		case HE:
+		    SAFECOPY(retbuf, "it");
+		    break;
+		case HIM:
+		    SAFECOPY(retbuf, "it");
+		    break;
+	    }
+    }
+    if (cap)
+	retbuf[0] = toupper(retbuf[0]);
+    return (retbuf);
+}
diff --git a/src/doors/dgnlance/utils.h b/src/doors/dgnlance/utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..4fda5adbe09c982c54220c40f72fa73eaf7e658d
--- /dev/null
+++ b/src/doors/dgnlance/utils.h
@@ -0,0 +1,9 @@
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+double supplant(void);
+void statshow(void);
+void pausescr(void);
+char *sexstrings(struct playertype * plr, int type, BOOL cap);
+
+#endif
\ No newline at end of file
diff --git a/src/doors/dgnlance/xp64.h b/src/doors/dgnlance/xp64.h
new file mode 100644
index 0000000000000000000000000000000000000000..af463129e7b2b90eff4002b48319862ed04810ae
--- /dev/null
+++ b/src/doors/dgnlance/xp64.h
@@ -0,0 +1,39 @@
+#ifndef INT64
+#ifdef _MSC_VER
+#define INT64	__int64
+#else
+#define INT64	long long int
+#endif
+#endif
+
+#ifndef INT64FORMAT
+#ifdef __BORLANDC__
+#define	INT64FORMAT	"Ld"
+#else
+#ifdef _MSC_VER
+#define INT64FORMAT	"I64d"
+#else
+#define INT64FORMAT		"lld"
+#endif
+#endif
+#endif
+
+#ifndef QWORD
+#ifdef _MSC_VER
+#define QWORD	unsigned _int64
+#else
+#define	QWORD	unsigned long long int
+#endif
+#endif
+
+#ifndef QWORDFORMAT
+#ifdef __BORLANDC__
+#define	QWORDFORMAT	"Lu"
+#else
+#ifdef _MSC_VER
+#define 	QWORDFORMAT	"I64u"
+#else
+#define 	QWORDFORMAT	"llu"
+#endif
+#endif
+#endif
diff --git a/src/doors/dgnlance/xpdev.c b/src/doors/dgnlance/xpdev.c
new file mode 100644
index 0000000000000000000000000000000000000000..1ca02509d9e73518127d80e79a8970069e106212
--- /dev/null
+++ b/src/doors/dgnlance/xpdev.c
@@ -0,0 +1,39 @@
+#include <string.h>
+#include <stdlib.h>		       /* RAND_MAX */
+#include <time.h>		       /* time() */
+
+#include "OpenDoor.h"		       /* BOOL */
+
+#include "xpdev.h"
+
+/****************************************************************************/
+/* Truncates all white-space chars off end of 'str'     (needed by STRERRROR)   */
+/****************************************************************************/
+char           *
+truncsp(char *str)
+{
+    size_t          i, len;
+    i = len = strlen(str);
+
+    while (i && (str[i - 1] == ' ' || str[i - 1] == '\t' || str[i - 1] == '\r' || str[i - 1] == '\n'))
+	i--;
+    if (i != len)
+	str[i] = 0;		       /* truncate */
+    return (str);
+}
+
+int
+xp_random(int n)
+{
+    float           f;
+    static BOOL     initialized;
+    if (!initialized) {
+	srand(time(NULL));	       /* seed random number generator */
+	rand();			       /* throw away first result */
+	initialized = TRUE;
+    }
+    if (n < 2)
+	return (0);
+    f = (float)rand() / (float)RAND_MAX;
+    return ((int)(n * f));
+}
diff --git a/src/doors/dgnlance/xpdev.h b/src/doors/dgnlance/xpdev.h
new file mode 100644
index 0000000000000000000000000000000000000000..a42977e6368a409c1b8c7f918068f4141aa628de
--- /dev/null
+++ b/src/doors/dgnlance/xpdev.h
@@ -0,0 +1,15 @@
+#ifndef _XPDEV_H_
+#define _XPDEV_H_
+
+#define SAFECOPY(dst, src) sprintf(dst, "%.*s", (int)sizeof(dst) - 1, src)
+#if defined(__unix__)
+#if !defined(stricmp)
+#define stricmp(x,y)            strcasecmp(x,y)
+#define strnicmp(x,y,z)         strncasecmp(x,y,z)
+#endif
+#endif
+
+char *truncsp(char *str);
+int xp_random(int n);
+
+#endif