diff --git a/xtrn/dgnlance/armour.js b/xtrn/dgnlance/armour.js
new file mode 100644
index 0000000000000000000000000000000000000000..7aec901b15ddaba1ffd2ec6d7b0b7dbdfef723b0
--- /dev/null
+++ b/xtrn/dgnlance/armour.js
@@ -0,0 +1,38 @@
+function Armour(name, power, cost)
+{
+	this.name=name;
+	this.cost=cost;
+	this.power=power;
+}
+
+// Read in the armour list...
+function sortarmourlist(a, b)
+{
+	if(a.power < b.power)
+		return(-1);
+	if(b.power < a.power)
+		return(1);
+	return(0);
+}
+
+var armourfile=new File(getpath()+"armours.ini");
+var armour=new Array();
+
+if(armourfile.open("r", true)) {
+	var all=armourfile.iniGetSections();
+
+	while(all.length) {
+		var name=all.shift();
+		var power=armourfile.iniGetValue(name, "Power", 1);
+		var cost=armourfile.iniGetValue(name, "Cost", 0);
+		armour.push(new Armour(name,power,cost));
+	}
+	armour.sort(sortarmourlist);
+}
+else {
+	console.attributes="HIR0";
+	/*console.*/writeln();
+	/*console.*/writeln("Cannot open armours file!"+armourfile.name);
+	/*console.*/writeln();
+	console.pause();
+}
diff --git a/xtrn/dgnlance/armours.ini b/xtrn/dgnlance/armours.ini
new file mode 100644
index 0000000000000000000000000000000000000000..02838bf08fea8b34e4bc0f11a8b36f6db1bd8e04
--- /dev/null
+++ b/xtrn/dgnlance/armours.ini
@@ -0,0 +1,100 @@
+[Tunic]
+Power=0
+Cost=0
+
+[Buckler Shield]
+Power=1
+Cost=100
+
+[Leather Armour]
+Power=2
+Cost=200
+
+[Chain Mail]
+Power=3
+Cost=400
+
+[Ring Mail]
+Power=4
+Cost=800
+
+[Plate Mail]
+Power=5
+Cost=1000
+
+[Field Plate Mail]
+Power=6
+Cost=2000
+
+[Full Plate Mail]
+Power=7
+Cost=4000
+
+[Tunic +1]
+Power=8
+Cost=6000
+
+[Buckler Shield +2]
+Power=9
+Cost=8000
+
+[Leather Armour +1]
+Power=10
+Cost=10000
+
+[Chain Mail +1]
+Power=11
+Cost=20000
+
+[Ring Mail +1]
+Power=12
+Cost=40000
+
+[Plate Mail +1]
+Power=13
+Cost=60000
+
+[Field Plate Mail +1]
+Power=14
+Cost=80000
+
+[Full Plate Mail +1]
+Power=15
+Cost=100000
+
+[Elven Chain Mail]
+Power=16
+Cost=200000
+
+[Magic Robe of Protection]
+Power=17
+Cost=400000
+
+[Dragon Highlord Armour]
+Power=18
+Cost=600000
+
+[Solamic Knight Armour]
+Power=19
+Cost=800000
+
+[Ring of Protection]
+Power=20
+Cost=1000000
+
+[Dragon Hide Armour]
+Power=21
+Cost=2000000
+
+[Companion Dragon]
+Power=22
+Cost=4000000
+
+[Magical Shield]
+Power=23
+Cost=8000000
+
+[Protection From Paladine]
+Power=24
+Cost=10000000
+
diff --git a/xtrn/dgnlance/dgnlance.ini b/xtrn/dgnlance/dgnlance.ini
new file mode 100644
index 0000000000000000000000000000000000000000..e8314998dec8083561198f5709382ba55f9f9bac
--- /dev/null
+++ b/xtrn/dgnlance/dgnlance.ini
@@ -0,0 +1,4 @@
+FightsPerDay=10
+BattlesPerDay=3
+FlightsPerDay=3
+LastRan=01/16/08
diff --git a/xtrn/dgnlance/dgnlance.js b/xtrn/dgnlance/dgnlance.js
new file mode 100644
index 0000000000000000000000000000000000000000..a5fa0438e517382ea9ce705df520ae5b689345b1
--- /dev/null
+++ b/xtrn/dgnlance/dgnlance.js
@@ -0,0 +1,761 @@
+load("sbbsdefs.js");
+load("lockfile.js");
+var Config = {
+	FLIGHTS_PER_DAY : 3,
+	BATTLES_PER_DAY : 3,
+	FIGHTS_PER_DAY : 10,
+	LASTRAN : "",
+};
+
+var required=new Array(
+	 0
+	,1500
+	,2800
+	,5500
+	,9000
+	,16000
+	,26000
+	,37000
+	,66000
+	,100000
+	,140000
+	,198000
+	,240000
+	,380000
+	,480000
+	,600000
+	,800000
+	,1000000
+	,2000000
+	,3000000
+	,4000000
+	,5000000
+	,6000000
+	,7000000
+	,8000000
+	,9000000
+	,10000000
+	,20000000
+	,30000000
+	,40000000
+);
+
+load(getpath()+"player.js");
+load(getpath()+"armour.js");
+load(getpath()+"weapon.js");
+// main()
+var player=new Player();
+
+exit(main());
+
+function getpath()
+{
+	return("../xtrn/dgnlance/");
+}
+
+function dgn_getkeys(keys)
+{
+	var key='';
+	keys=keys.toUpperCase();
+	while(1) {
+		key=console.getkey(K_UPPER|K_NOCRLF);
+		if(key=='')
+			return(key);
+		if(keys.indexOf(key)!=-1)
+			return(key);
+	}
+}
+
+function checkday()
+{
+	var newday=false;
+	var bfile=new File(getpath()+"btoday.asc");
+
+	if(Config.LASTRAN != system.datestr()) {
+		Config.LASTRAN = system.datestr();
+		var conf=new File(getpath()+"dgnlance.ini");
+		if(conf.open("r+",true)) {
+			conf.iniSetValue(null, "LastRan", Config.LASTRAN);
+			newday=true;
+			conf.close();
+		}
+	}
+
+	if(newday) {
+		var all=getplayerlist();
+		var i;
+		for(i=0; i<all.length; i++) {
+			all[i].battles=Config.BATTLES_PER_DAY;
+			all[i].flights=Config.FLIGHTS_PER_DAY;
+			all[i].fights=Config.FIGHTS_PER_DAY;
+			all[i].status &= ~Status.DEAD;
+			all[i].damage=0;
+			all[i].vary=supplant();
+			all[i].save();
+		}
+		file_remove(getpath()+"yester.log");
+		file_rename(getpath()+"today.log", getpath()+"yester.log");
+		file_remove(getpath()+"byester.asc");
+		file_rename(getpath()+"btoday.asc", getpath()+"byester.asc");
+		if(bfile.open("w")) {
+			bfile.writeln(system.datestr()+": A new day begins...");
+			bfile.writeln();
+			bfile.close();
+		}
+	}
+}
+
+function playerlist()
+{
+	var list=getplayerlist();
+	var i;
+
+	console.attributes="M0";
+	/*console.*/writeln("Hero Rankings:");
+	/*console.*/writeln("!!!!!!!!!!!!!!");
+	for(i=0; i<list.length; i++) {
+		console.attributes="M0";
+		console.print(format("%2u. \x01H\x01C%.30s%.*s\x01N\x01GLev=%-2u  W=%-6u L=%-6u S=%s \x01I\x01R%s\r\n"
+			, i+1
+			, list[i].pseudo
+			, 30-list[i].pseudo.length
+			, '...............................'
+			, list[i].level
+			, list[i].wins
+			, list[i].losses
+			, (list[i].status & Status.DEAD)?"SLAIN":"ALIVE"
+			, (list[i].status & Status.ONLINE)?"ONLINE":""
+		));
+		if(((i+1) % console.rows)==0)
+			console.pause();
+	}
+}
+
+function weaponlist()
+{
+	var i;
+	var max=weapon.length;
+
+	if(max<armour.length)
+		max=armour.length;
+
+    /*console.*/writeln("Num. Weapon                    Price       Armour                    Price");
+	/*console.*/writeln("------------------------------------------------------------------------------");
+	for(i=1; i<max; i++) {
+		if((i < weapon.length && weapon[i].cost != 0) || (i < armour.length && armour[i].cost != 0)) {
+			/*console.*/writeln(format("%2d>  %-25.25s %9s   %-25.25s %9s"
+					, i
+					, ((i>=weapon.length || weapon[i].cost==0)?"":weapon[i].name)
+					, ((i>=weapon.length || weapon[i].cost==0)?"":weapon[i].cost)
+					, ((i>=armour.length || armour[i].cost==0)?"":armour[i].name)
+					, ((i>=armour.length || armour[i].cost==0)?"":armour[i].cost)
+		));
+		}
+	}
+}
+
+function credits()
+{
+	console.clear();
+	console.attributes="G0";
+	/*console.*/writeln("Dragonlance 3.0 Credits");
+	/*console.*/writeln("@@@@@@@@@@@@@@@@@@@@@@@");
+	/*console.*/writeln("Original Dragonlance   : Raistlin Majere & TML");
+	/*console.*/writeln("Special Thanks To      : The Authours of Dragonlance");
+	/*console.*/writeln("Drangonlance's Home    : The Tower Of High Sorcery");
+	/*console.*/writeln("Originally modified from the Brazil Source Code");
+	/*console.*/writeln("C Port                 : Deuce");
+	/*console.*/writeln("JavaScript Port        : Deuce");
+	/*console.*/writeln("Home Page              : http://doors.bbsdev.net/");
+	/*console.*/writeln("Support                : deuce@nix.synchro.net");
+	/*console.*/writeln();
+	console.pause();
+}
+
+function docs()
+{
+	console.clear();
+	console.printfile(getpath()+"docs.asc");
+	
+}
+
+function listplayers()
+{
+	console.clear();
+	console.attributes="HY0";
+	/*console.*/writeln("Heroes That Have Been Defeated");
+	/*console.*/writeln("++++++++++++++++++++++++++++++");
+	console.attributes="HC0";
+	if(file_exists(getpath()+"yester.log"))
+		console.printfile(getpath()+"yester.log");
+	if(file_exists(getpath()+"today.log"))
+		console.printfile(getpath()+"today.log");
+}
+
+function loadconfig()
+{
+	var conf=new File(getpath()+"dgnlance.ini");
+
+	if(conf.open("r",true)) {
+		Config.FLIGHTS_PER_DAY=conf.iniGetValue(null, "FlightsPerDay", Config.FLIGHTS_PER_DAY);
+		Config.BATTLES_PER_DAY=conf.iniGetValue(null, "BattlesPerDay", Config.BATTLES_PER_DAY);
+		Config.FIGHTS_PER_DAY=conf.iniGetValue(null, "FightsPerDay", Config.FIGHTS_PER_DAY);
+		Config.LASTRAN=conf.iniGetValue(null, "LastRan", "");
+		conf.close();
+	}
+}
+
+function weaponshop()
+{
+	var buy=0;
+	var buyprice=0;
+	var type="";
+	var max=weapon.length;
+
+	if(max<armour.length)
+		max=armour.length;
+
+	console.clear();
+	console.attributes="HY0";
+	/*console.*/writeln("Weapon & Armour Shop");
+	console.attributes="G0";
+	/*console.*/writeln("$$$$$$$$$$$$$$$$$$$$");
+	while(1) {
+		/*console.*/writeln();
+		console.write("(B)rowse, (S)ell, (P)urchase, or (Q)uit? ");
+		switch(dgn_getkeys("BSQP")) {
+			case 'Q':
+				/*console.*/writeln("Quit");
+				return;
+			case 'B':
+				/*console.*/writeln("Browse");
+				weaponlist();
+				break;
+			case 'P':
+				/*console.*/writeln("Purchase");
+				/*console.*/writeln();
+				/*console.*/writeln();
+				console.write("Enter weapon/armour # you wish to buy: ");
+				buy=console.getnum(max);
+				if(buy==0)
+					continue;
+				/*console.*/writeln();
+				if(buy >= weapon.length)
+					type="A";
+				else if(buy >= armour.length)
+					type="W";
+				else {
+					console.write("(W)eapon or (A)rmour: ");
+					type=dgn_getkeys("WA");
+					if(type=='A')
+						/*console.*/writeln("Armour");
+					else if(type=='W')
+						/*console.*/writeln("Weapon");
+					else
+						continue;
+				}
+				switch(type) {
+					case 'W':
+						if(weapon[buy].cost==0) {
+							/*console.*/writeln("You want to buy a what?");
+							continue;
+						}
+						console.write("Are you sure you want to buy it? ");
+						if(dgn_getkeys("YN")=='Y') {
+							/*console.*/writeln("Yes");
+							if(weapon[buy].cost > player.gold) {
+								/*console.*/writeln("You do not have enough Steel.");
+								continue;
+							}
+							if(weapon[buy].cost==0) {
+								/*console.*/writeln("You can not buy one of those...");
+								continue;
+							}
+							player.gold -= weapon[buy].cost;
+							player.weapon=new Weapon(weapon[buy].name, weapon[buy].attack, weapon[buy].power, weapon[buy].cost);
+							/*console.*/writeln();
+							console.attributes="M0";
+							/*console.*/writeln("You've bought a "+player.weapon.name);
+						}
+						else
+							/*console.*/writeln("No");
+						break;
+					case 'A':
+						if(weapon[buy].cost==0) {
+							/*console.*/writeln("You want to buy a what?");
+							continue;
+						}
+						console.write("Are you sure you want to buy it? ");
+						if(dgn_getkeys("YN")=='Y') {
+							/*console.*/writeln("Yes");
+							if(armour[buy].cost > player.gold) {
+								/*console.*/writeln("You do not have enough Steel.");
+								continue;
+							}
+							if(armour[buy].cost==0) {
+								/*console.*/writeln("You can not buy one of those...");
+								continue;
+							}
+							player.gold -= armour[buy].cost;
+							player.armour=new Armour(armour[buy].name, armour[buy].power, armour[buy].cost);
+							/*console.*/writeln();
+							console.attributes="M0";
+							/*console.*/writeln("You've bought a "+player.armour.name);
+						}
+						else
+							/*console.*/writeln("No");
+						break;
+				}
+				break;
+			case 'S':
+				/*console.*/writeln("Sell");
+				/*console.*/writeln();
+				console.write("(W)eapon, (A)rmour, (Q)uit: ");
+				switch(dgn_getkeys("AWQ")) {
+					case 'Q':
+						/*console.*/writeln("Quit");
+						break;
+					case 'W':
+						/*console.*/writeln("Weapon");
+						buyprice=player.charisma;
+						buyprice*=player.weapon.cost;
+						buyprice/=20;
+						/*console.*/writeln();
+						console.write("I will purchase it for "+buyprice+", okay? ");
+						if(dgn_getkeys("YN")=='Y') {
+							/*console.*/writeln("Yes");
+							console.attributes="G0";
+							/*console.*/writeln("Is it Dwarven Made?");
+							player.weapon=new Weapon(weapon[0].name, weapon[0].attack, weapon[0].power, weapon[0].cost);
+							player.gold += buyprice;
+						}
+						else
+							/*console.*/writeln("No");
+						break;
+					case 'A':
+						/*console.*/writeln("Armour");
+						buyprice=player.charisma;
+						buyprice*=player.armour.cost;
+						buyprice/=20;
+						/*console.*/writeln();
+						console.write("I will purchase it for "+buyprice+", okay? ");
+						if(dgn_getkeys("YN")=='Y') {
+							/*console.*/writeln("Yes");
+							/*console.*/writeln("Fine Craftsmanship!");
+							player.armour=new Armour(armour[0].name, armour[0].power, armour[0].cost);
+							player.gold += buyprice;
+						}
+						else
+							/*console.*/writeln("No");
+						break;
+
+				}
+				break;
+		}
+	}
+}
+
+function spy()
+{
+	var users=getplayerlist();
+	var spyon;
+
+	console.clear();
+	/*console.*/writeln("Spying on another user eh.. well you may spy, but to keep");
+	/*console.*/writeln("you from copying this person's stats, they will not be");
+	/*console.*/writeln("available to you.  Note that this is gonna cost you some");
+	/*console.*/writeln("cash too.  Cost: 20 Steel pieces");
+	/*console.*/writeln();
+	console.write("Who do you wish to spy on? ");
+	spyon=console.getstr("", 30, K_LINE);
+	if(spyon=='')
+		return;
+	if(player.gold < 20) {
+		console.attributes="HR0";
+		/*console.*/writeln("You do not have enough Steel!");
+	}
+	else {
+		/* Find this user */
+		for(i=0; i<users.length; i++) {
+			if(i.pseudo.match(new RegExp("spyon","i")!=-1)) {
+				console.write("Do you mean \""+users[i].pseudo+"\"?");
+				if(dgn_getkeys("YN")=="Y") {
+					/*console.*/writeln("Yes");
+					break;
+				}
+				/*console.*/writeln("No");
+			}
+		}
+		if(i>=users.length)
+			return;
+	
+		player.gold -= 20;
+		/*console.*/writeln();
+		console.attributes="HR0";
+		/*console.*/writeln(users[i].pseudo);
+		/*console.*/writeln();
+		/*console.*/writeln("Level  : "+users[i].level);
+		/*console.*/writeln("Exp    : "+users[i].experience);
+		/*console.*/writeln("Flights: "+users[i].flights);
+		/*console.*/writeln("HPs    : "+users[i].hps);
+		/*console.*/writeln();
+		console.attributes="M0";
+		/*console.*/writeln("Weapon : "+users[i].weapon.name);
+		/*console.*/writeln("Armour : "+users[i].armour.name);
+		/*console.*/writeln();
+		console.attributes="HY0";
+		/*console.*/writeln("Steel  (in hand): "+users[i].gold);
+		/*console.*/writeln("Steel  (in bank): "+users[i].bank);
+		/*console.*/writeln();
+		console.pause();
+	}
+}
+
+function bulletin()
+{
+	var bfile=new File(getpath()+"btoday.asc");
+	var bline="";
+
+	console.clear();
+	if(file_exists(getpath()+"byester.asc"))
+		console.printfile(getpath()+"byester.asc");
+	if(file_exists(getpath()+"btoday.asc"))
+		console.printfile(getpath()+"btoday.asc");
+	/*console.*/writeln();
+	console.write("Do you wish to enter a News Bulletin? ");
+	if(dgn_getkeys("YN")=='Y') {
+		/*console.*/writeln("Yes");
+		/*console.*/writeln();
+		var bullet=new Array();;
+		while(bullet.length<4) {
+			console.attributes="HY0";
+			console.write((bullet.length+1)+"> ");
+			console.attributes="W0";
+			bline=console.getstr("", 60, K_LINE);
+			if(bline=="")
+				break;
+			bullet.push(bline);
+		}
+		/*console.*/writeln();
+		console.write("Is the bulletin correct? ");
+		if(dgn_getkeys("YN")=='Y') {
+			/*console.*/writeln("Yes");
+			/*console.*/writeln("Saving Bulletin...");
+			if(bfile.open("a",true)) {
+				bfile.writeln("At "+system.timestr()+", "+player.pseudo+" wrote:");
+				while(bullet.length) {
+					bfile.write("     ");
+					bfile.writeln(bullet.shift());
+				}
+				bfile.writeln();
+				bfile.close();
+			}
+		}
+		else
+			/*console.*/writeln("No");
+	}
+	else
+		/*console.*/writeln("No");
+}
+
+function afight(lvl)
+{
+	var monsters;
+	var monster;
+
+	if(player.fights<1) {
+		/*console.*/writeln();
+		console.attributes="M0";
+		/*console.*/writeln("It's Getting Dark Out!");
+		/*console.*/writeln("Return to the Nearest Inn!");
+	}
+	else {
+		console.clear();
+		monsters=getplayerlist(getpath()+"monsters"+lvl+".ini");
+		if(monsters.length < 1)
+			return;
+		monster=monsters[random(monsters.length)];
+		monster.status=Status.MONSTER;
+		monster.weapon.attack *= supplant();
+		if(monster.weapon.attack<1)
+			monster.weapon.attack=1;
+		monster.weapon.power *= supplant();
+		if(monster.weapon.power<1)
+			monster.weapon.power=1;
+		monster.armour.power *= supplant();
+		if(monster.armour.power<1)
+			monster.armour.power=1;
+		monster.luck *= supplant();
+		if(monster.luck<1)
+			monster.luck=1;
+		monster.strength *= supplant();
+		if(monster.strength<1)
+			monster.strength=1;
+		monster.dexterity *= supplant();
+		if(monster.dexterity<1)
+			monster.dexterity=1;
+		monster.hps *= supplant();
+		if(monster.hps<1)
+			monster.hps=1;
+		monster.vary=supplant();
+		player.fights--;
+		player.battle(monster);
+	}
+}
+
+function doggie()
+{
+	var players;
+	var avail_players=new Array();
+	var i;
+	var opp=0;
+
+	if(player.battles > 0) {
+		console.clear();
+		console.attributes="HY0";
+		/*console.*/writeln("Battle Another Hero");
+		/*console.*/writeln("*******************");
+		players=getplayerlist();
+		for(i=0; i<players.length; i++) {
+			if((players[i].level > player.level-4)
+					&& players[i].name!=player.name
+					&& (players[i].status & Status.DEAD)==0
+					/* TODO: Allow internode battles */
+					&& (players[i].status & Status.ONLINE)==0) {
+				avail_players.push(players[i]);
+				console.print(format("\01N\01H\01Y%2u.  \01H\01C%.30s%.*s\01BLev=%-2u  W=%-2d  L=%-2dS=%s \01I\01R%s\r\n"
+					, avail_players.length
+					, players[i].pseudo
+					, 30-players[i].pseudo.length
+					, "..............................."
+					, players[i].level
+					, players[i].wins
+					, players[i].losses
+					, "ALIVE"
+					, ""));
+				if(avail_players.length % (console.rows-1))
+					console.pause();
+			}
+		}
+		/*console.*/writeln();
+		console.attributes="HC0";
+		console.write("Enter the # of your opponent: ");
+		opp=console.getnum(avail_players.length);
+		if(opp>0 && opp<=avail_players.length) {
+			opp--;
+			avail_players[opp].status &= Status.PLAYER;
+			avail_players[opp].status &= ~Status.MONSTER;
+			player.battles--;
+			avail_players[opp].experience /= 10;
+			avail_players[opp].damage = 0;
+			/*console.*/writeln();
+			/*console.*/writeln("Your opponent screams out:");
+			/*console.*/writeln('"'+avail_players[opp].bcry+'" as battle is joined.');
+			/*console.*/writeln();
+			player.battle(avail_players[opp]);
+		}
+	}
+}
+
+function main()
+{
+	console.line_counter=0;
+	loadconfig();
+	checkday();
+	credits();
+	console.clear();
+	console.print("\x01H\x01Y----------\x01N\x01I\x01R   -=-=DRAGONLANCE=-=-     \x01N\x01H\x01Y     /\\     \r\n");
+	console.print("\\        /\x01N\x01W       Version 3.0          \x01H\x01Y    ||     \r\n");
+	console.print(" \\      /                                 ||     \r\n");
+	console.print("  \\    /  \x01B  Welcome To The World of   \x01Y    ||     \r\n");
+	console.print("   |  |   \x01C  Krynn, Where the gods     \x01Y    ||     \r\n");
+	console.print("  /    \\  \x01B  of good and evil battle.  \x01Y  \\ || /   \r\n");
+	console.print(" /      \\ \x01C  Help the People Of Krynn. \x01Y   \\==/    \r\n");
+	console.print("/        \\                                ##     \r\n");
+	console.print("----------\x01N\x01I\x01R        ON WARD!!!          \x01N\x01H\x01Y    ##     \r\n");
+	/*console.*/writeln();
+	/*console.*/writeln("News Bulletin:");
+	/*console.*/writeln();
+	if(file_exists(getpath()+"byester.asc"))
+		console.printfile(getpath()+"byester.asc");
+	if(file_exists(getpath()+"btoday.asc"))
+		console.printfile(getpath()+"btoday.asc");
+	if(!player.load())
+		player.create(true);
+	js.on_exit("player.leave()");
+	if(player.status & Status.DEAD) {
+		if(player.laston==system.datestr()) {
+			/*console.*/writeln("You have already died today...");
+			/*console.*/writeln("Return tomorrow for your revenge!");
+			return(0);
+		}
+		/*console.*/writeln();
+		console.attributes="HC0";
+		/*console.*/writeln("A defeat was lead over you by "+player.killer);
+	}
+	player.lastone=system.datestr();
+	if(player.flights < 1) {
+		player.fights=0;
+		player.battles=0;
+	}
+	else
+		player.flights--;
+	/*console.*/writeln();
+	console.pause();
+	console.clear();
+	console.attributes="HY0";
+	player.status &= Status.ONLINE;
+	player.statshow();
+	player.save();
+	while(player.damage < player.hps) {
+		player.levelupdate();
+		if((player.wins+1)*4 < player.losses) {
+			/*console.*/writeln();
+			/*console.*/writeln("As you were Travelling along a Wilderness Page an");
+			/*console.*/writeln("Evil Wizard Confronted You. When you tried to fight");
+			/*console.*/writeln("Him off, he cast a Spell of Instant Death Upon you.");
+			/*console.*/writeln("Instantly you were slain by the Archmage, Leaving you");
+			/*console.*/writeln("as nothing more than a pile of ashes. Re-Rolled!");
+			/*console.*/writeln();
+			console.pause();
+			player.create(false);
+			if(player.flights)
+				player.flights--;
+		}
+		/*console.*/writeln();
+		/*console.*/writeln();
+		console.attributes="HY0";
+		console.write("Command (?): ");
+		switch(dgn_getkeys("QVP12345CHWLADGFRSTX+-?EZ*#")) {
+			case 'Q':
+				/*console.*/writeln("Quit");
+				console.write("LEAVE KRYNN? Are you sure? ");
+				if(dgn_getkeys("YN")=='Y') {
+					/*console.*/writeln("Yes");
+					return(0);
+				}
+				/*console.*/writeln("No");
+				break;
+			case '1':
+				/*console.*/writeln("1");
+				afight(1);
+				break;
+			case '2':
+				/*console.*/writeln("2");
+				afight(2);
+				break;
+			case '3':
+				/*console.*/writeln("3");
+				afight(3);
+				break;
+			case '4':
+				/*console.*/writeln("4");
+				afight(4);
+				break;
+			case '5':
+				/*console.*/writeln("5");
+				afight(5);
+				break;
+			case 'C':
+				/*console.*/writeln("Change Stats");
+				player.chstats();
+				break;
+			case 'H':
+				/*console.*/writeln("Heal");
+				player.heal();
+				break;
+			case 'W':
+				/*console.*/writeln("Weapon Shop");
+				weaponshop();
+				break;
+			case 'L':
+				/*console.*/writeln("Level Update");
+				player.levelupdate();
+				break;
+			case 'A':
+				/*console.*/writeln("Battle Another User");
+				doggie();
+				break;
+			case 'D':
+				/*console.*/writeln("Docs");
+				docs();
+				break;
+			case 'G':
+				/*console.*/writeln("Gamble");
+				player.gamble();
+				break;
+			case 'F':
+				/*console.*/writeln("Battles Today");
+				listplayers();
+				break;
+			case 'R':
+				/*console.*/writeln("Rank Players");
+				playerlist();
+				break;
+			case 'S':
+				/*console.*/writeln("Status");
+				player.statshow();
+				break;
+			case 'T':
+				/*console.*/writeln("Training Grounds");
+				player.training();
+				break;
+			case 'X':
+				/*console.*/writeln("Re-Roll");
+				/*console.*/writeln("Please not that this will completely purge");
+				/*console.*/writeln("your current hero of all attributes!");
+				/*console.*/writeln();
+				console.write("Are you sure you want to REROLL your character? ");
+				if(dgn_getkeys("YN")=='Y') {
+					/*console.*/writeln("Yes");
+					player.create(false);
+					if(player.flights)
+						player.flights--;
+				}
+				else
+					/*console.*/writeln("No");
+				break;
+			case '+':
+				/*console.*/writeln("Deposit");
+				player.depobank();
+				break;
+			case '-':
+				/*console.*/writeln("Withdraw");
+				player.withdrawbank();
+				break;
+			case 'P':
+				/*console.*/writeln("Plug");
+				console.clear();
+				console.printfile(getpath()+"plug.asc");
+				break;
+			case '?':
+				/*console.*/writeln("Help");
+				console.clear();
+				console.printfile(getpath()+"menu.asc");
+				break;
+			case 'E':
+				/*console.*/writeln("Edit Announcement");
+				bulletin();
+				break;
+			case 'Z':
+				/*console.*/writeln("Spy");
+				spy();
+				break;
+			case 'V':
+				/*console.*/writeln("Version");
+				console.attributes="HB0";
+				/*console.*/writeln("This Is Dragonlance version 3.0 (JS)");
+				console.pause();
+				break;
+			case '*':
+				/*console.*/writeln("Change Name");
+				player.changename();
+				break;
+			case '#':
+				/*console.*/writeln("Change Battle Cry");
+				player.vic();
+				break;
+		}
+	}
+	return(0);
+}
diff --git a/xtrn/dgnlance/docs.asc b/xtrn/dgnlance/docs.asc
new file mode 100644
index 0000000000000000000000000000000000000000..b5de85ae02bfcd27d93dc71c25cf056d8d8ddc0b
--- /dev/null
+++ b/xtrn/dgnlance/docs.asc
@@ -0,0 +1,57 @@
+
+                                 Dragonlance COMMANDS
+                                 !!!!!!!!!!!!!!!!!!!!
+
+   1-4  - Entering numbers 1 thru 4 will allow you to attack various monsters
+          according to level.  4 being the greatest of levels and 1 being the
+          the lowest.
+
+   A/B  - Engage in character to character battle.
+
+    C   - Change Status.  Use this command to increase your attributes, please
+          note that you will have to decrease another stat inturn.
+
+    D   - Documentation.
+
+    E   - Enter a Announcement.  You are permitted to change the war
+          bulletin at will.  Use this to read the bulletin and write a new
+          one.
+
+    F   - Lists the fights of the day.
+
+    G   - Gamble for Steel  Pieces.  Odds are 100 to 1 that you will win the
+          maximum prize.  Prizes go in this fashion: 100:1 ... 10:1 ... 3:1.
+
+    H   - Heal your status.. it will cost you Steel  according to your level.
+          Press return at any time to heal all ht points.
+
+    Q   - None other than the notorious QUIT THE GAME.
+
+    R   - Rank the players according to obtained experience points.
+
+    S   - Show your status
+
+    T   - Training Grounds.  Here you can increase a stat w/o decreasing
+          another.  The only disadvantage being the enormous cost!
+
+    X   - Becareful.. this will RE-ROLL your character if you wish it to
+          happen.
+
+    Z   - Spy on another user.  This will cost you nothing but a measly
+          20 Steel  pieces, and spy away.. all ya want.  More info with
+          the 'Z' command.
+
+    +   - Deposit Steel in the bank (no one can steel it here!);
+
+    -   - Withdraw all Steel, please note that if you forget to deposit it
+          after you quit and someone plays, they can steel your money!
+
+    *   - Change your Emblem.  Change your name to whatever you want.
+          note there are some trickey things you can do with your name so
+          it's difficult to spy on people.
+
+    P   - A Little Plug For My BBS
+
+    #   - Change your battle cry.  Utter any oath you like!!!
+
+    V   - Version Info and How To Reach Author
diff --git a/xtrn/dgnlance/guards.asc b/xtrn/dgnlance/guards.asc
new file mode 100644
index 0000000000000000000000000000000000000000..67fdf1fa8655542076eb4da0d31cef4fbb39c45a
--- /dev/null
+++ b/xtrn/dgnlance/guards.asc
@@ -0,0 +1,18 @@
+lw 
+You Have Entered the Last Realm of the Game!!! Welcome To the Abyss!!!!!
+Here you must Battle 2 Guards and then Thakisis To Enter your Name in the
+Hall Of Fame!!!!!! Beware!!!!
+�hg__nw  hg__�__nw  hg__
+�nw_hg\/nw_�/-------------------------\�_hg\/nw_
+�(_)(_)�|  ENTER AT YOUR OWN RISK!  |�(_)(_)
+�g(__)�w\-------------------------/�g(__)
+�__)(__�__)(__
+�hg/�\�/�\
+�\nw hy!nw  hy!nw hg/�\nw hy!nw  hy!nw hg/
+�y g\y|ny==hy|g/�\y|ny==hy|g/
+�ng/�\�/�\
+�hg\�/�\�/
+�\nw  hg/�\nw  hg/
+�nwoO)(Oo�oO)(Oo
+�
+n
\ No newline at end of file
diff --git a/xtrn/dgnlance/menu.asc b/xtrn/dgnlance/menu.asc
new file mode 100644
index 0000000000000000000000000000000000000000..7c6e2ca4c1641c827e2b0b9256a2d7431e9869d2
--- /dev/null
+++ b/xtrn/dgnlance/menu.asc
@@ -0,0 +1,18 @@
+lhb 
+�nb+hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb>nwDRAGONLANCE 3.0hb<nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb+
+�|w 1  -- Level 1 Creatures�H  -- Heal wounds�b|
+�|w 2  -- Level 2 Creatures�Q  -- Quit Game�b|
+�|w 3  -- Level 3 Creatures�R  -- Rank Players�b|
+�hb|nw 4  -- Level 4 Creatures�S  -- Status�hb|
+�|nw 5  -- Level 5 Creatures�T  -- Training Grounds hb|
+�|nw A  -- Battle another user�W  -- Weapons Shoppe�hb|
+�|nw C  -- Change stats�X  -- Re-Roll Characterhb|
+�|nw D  -- Docs�Z  -- Spy On Another�hb|
+�|nw E  -- Edit Announcement�G  -- Gambling�hb|
+�|nw F  -- Battles Today�-  -- Withdraw Steel�hb|
+�|nw ?  -- Help Menu�*  -- Change Name�hb|
+�nb|w +  -- Deposit Steel�P  -- Plug For Author  b|
+�|w #  -- Change Battle Cry�V  -- Version Info�b|
+�|w L  -- Level Update�b|
+�+hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb=hb-nb+
+w 
diff --git a/xtrn/dgnlance/monsters1.ini b/xtrn/dgnlance/monsters1.ini
new file mode 100644
index 0000000000000000000000000000000000000000..bb5d9031c4b3e0b9b2fa0f440b975c7fad14a08f
--- /dev/null
+++ b/xtrn/dgnlance/monsters1.ini
@@ -0,0 +1,96 @@
+[Goblin]
+Dexterity=14
+GoldOnHand=20
+Luck=6
+HitPoints=11
+WeaponPower=1
+WeaponAttack=2
+Strength=9
+Experience=43
+ArmourPower=1
+Sex=I
+
+[Ghost]
+Dexterity=10
+GoldOnHand=200
+Luck=8
+HitPoints=12.45
+WeaponPower=2
+WeaponAttack=2
+Strength=13
+Experience=135
+ArmourPower=1
+Sex=I
+
+[Ogre]
+Dexterity=10
+GoldOnHand=400
+Luck=12
+HitPoints=13
+WeaponPower=1
+WeaponAttack=3
+Strength=11
+Experience=200
+ArmourPower=1
+Sex=I
+
+[Hobgoblin]
+Dexterity=9
+GoldOnHand=300
+Luck=8
+HitPoints=10
+WeaponPower=3
+WeaponAttack=2
+Strength=8
+Experience=220
+ArmourPower=1
+Sex=I
+
+[Orc]
+Dexterity=10
+GoldOnHand=380
+Luck=9
+HitPoints=12
+WeaponPower=1
+WeaponAttack=1
+Strength=9
+Experience=200
+ArmourPower=2
+Sex=I
+
+[Draconian Type 1]
+Dexterity=7
+GoldOnHand=330
+Luck=12
+HitPoints=7
+WeaponPower=1
+WeaponAttack=2
+Strength=8
+Experience=300
+ArmourPower=2
+Sex=I
+
+[Draconian Type 2]
+Dexterity=13
+GoldOnHand=600
+Luck=11
+HitPoints=12
+WeaponPower=2
+WeaponAttack=2
+Strength=10
+Experience=400
+ArmourPower=1
+Sex=I
+
+[Human Spy]
+Dexterity=12
+GoldOnHand=325
+Luck=12
+HitPoints=10
+WeaponPower=2
+WeaponAttack=2
+Strength=12
+Experience=245
+ArmourPower=1
+Sex=I
+
diff --git a/xtrn/dgnlance/monsters2.ini b/xtrn/dgnlance/monsters2.ini
new file mode 100644
index 0000000000000000000000000000000000000000..305ad784849c6e5d96ce2d63748b0be1f188a587
--- /dev/null
+++ b/xtrn/dgnlance/monsters2.ini
@@ -0,0 +1,96 @@
+[Draconian Type 3]
+Dexterity=12
+GoldOnHand=800
+Luck=13
+HitPoints=15.65
+WeaponPower=3
+WeaponAttack=4
+Strength=14
+Experience=1200
+ArmourPower=3
+Sex=I
+
+[Draconian Type 4]
+Dexterity=14
+GoldOnHand=500
+Luck=10
+HitPoints=15
+WeaponPower=3
+WeaponAttack=4
+Strength=15
+Experience=600
+ArmourPower=1
+Sex=I
+
+[Draconian Type 5]
+Dexterity=15
+GoldOnHand=450
+Luck=14
+HitPoints=20
+WeaponPower=4
+WeaponAttack=5
+Strength=15
+Experience=500
+ArmourPower=5
+Sex=I
+
+[Draconian Type 6]
+Dexterity=12
+GoldOnHand=500
+Luck=12
+HitPoints=20
+WeaponPower=4
+WeaponAttack=5
+Strength=13
+Experience=650
+ArmourPower=6
+Sex=I
+
+[Draconian Type 7]
+Dexterity=14
+GoldOnHand=700
+Luck=14
+HitPoints=18
+WeaponPower=4
+WeaponAttack=4
+Strength=15
+Experience=790
+ArmourPower=3
+Sex=I
+
+[Draconian Type 8]
+Dexterity=16
+GoldOnHand=900
+Luck=13
+HitPoints=25
+WeaponPower=4
+WeaponAttack=5
+Strength=14
+Experience=900
+ArmourPower=3
+Sex=I
+
+[Draconian Type 9]
+Dexterity=15
+GoldOnHand=975
+Luck=14
+HitPoints=25
+WeaponPower=5
+WeaponAttack=5
+Strength=15
+Experience=1700
+ArmourPower=5
+Sex=I
+
+[Draconian Type 10]
+Dexterity=12
+GoldOnHand=860
+Luck=12
+HitPoints=23
+WeaponPower=4
+WeaponAttack=4
+Strength=15
+Experience=999
+ArmourPower=4
+Sex=I
+
diff --git a/xtrn/dgnlance/monsters3.ini b/xtrn/dgnlance/monsters3.ini
new file mode 100644
index 0000000000000000000000000000000000000000..037022c0842ab68ff9f8bbb96d53c77f0999e915
--- /dev/null
+++ b/xtrn/dgnlance/monsters3.ini
@@ -0,0 +1,96 @@
+[Drow]
+Dexterity=16
+GoldOnHand=2000
+Luck=15
+HitPoints=30
+WeaponPower=9
+WeaponAttack=7
+Strength=16
+Experience=2400
+ArmourPower=8
+Sex=I
+
+[Giant Spider]
+Dexterity=14
+GoldOnHand=3000
+Luck=14
+HitPoints=55
+WeaponPower=9
+WeaponAttack=8
+Strength=12
+Experience=2512
+ArmourPower=12
+Sex=I
+
+[Skeleton Warrior]
+Dexterity=13
+GoldOnHand=2530
+Luck=12
+HitPoints=48
+WeaponPower=9
+WeaponAttack=7
+Strength=12
+Experience=1815
+ArmourPower=6
+Sex=I
+
+[Giant Rat]
+Dexterity=17
+GoldOnHand=1450
+Luck=15
+HitPoints=35
+WeaponPower=10
+WeaponAttack=9
+Strength=14
+Experience=2987
+ArmourPower=7
+Sex=I
+
+[Wraith]
+Dexterity=14
+GoldOnHand=2500
+Luck=14
+HitPoints=65
+WeaponPower=10
+WeaponAttack=10
+Strength=14
+Experience=4500
+ArmourPower=7
+Sex=I
+
+[Zombie]
+Dexterity=15
+GoldOnHand=1250
+Luck=12
+HitPoints=57
+WeaponPower=6
+WeaponAttack=10
+Strength=10
+Experience=2050
+ArmourPower=12
+Sex=I
+
+[Black Robed Wizard]
+Dexterity=13
+GoldOnHand=4500
+Luck=15
+HitPoints=65
+WeaponPower=10
+WeaponAttack=7
+Strength=16
+Experience=6500
+ArmourPower=7
+Sex=I
+
+[Renegade Wizard]
+Dexterity=17
+GoldOnHand=3500
+Luck=15
+HitPoints=48
+WeaponPower=7
+WeaponAttack=9
+Strength=13
+Experience=4300
+ArmourPower=5
+Sex=I
+
diff --git a/xtrn/dgnlance/monsters4.ini b/xtrn/dgnlance/monsters4.ini
new file mode 100644
index 0000000000000000000000000000000000000000..f82276db0bd1833f078c55345c9cdb9e44291124
--- /dev/null
+++ b/xtrn/dgnlance/monsters4.ini
@@ -0,0 +1,96 @@
+[White Dragon]
+Dexterity=16
+GoldOnHand=9000
+Luck=17
+HitPoints=65
+WeaponPower=17
+WeaponAttack=15
+Strength=18
+Experience=7550
+ArmourPower=14
+Sex=I
+
+[Green Dragon]
+Dexterity=19
+GoldOnHand=10000
+Luck=18
+HitPoints=125
+WeaponPower=18
+WeaponAttack=12
+Strength=16
+Experience=18000
+ArmourPower=16
+Sex=I
+
+[Red Dragon]
+Dexterity=17
+GoldOnHand=5000
+Luck=19
+HitPoints=45
+WeaponPower=13
+WeaponAttack=12
+Strength=17
+Experience=4500
+ArmourPower=12
+Sex=I
+
+[Blue Dragon]
+Dexterity=18
+GoldOnHand=25000
+Luck=18
+HitPoints=120
+WeaponPower=18
+WeaponAttack=18
+Strength=18
+Experience=49000
+ArmourPower=18
+Sex=I
+
+[Black Dragon]
+Dexterity=17
+GoldOnHand=67000
+Luck=20
+HitPoints=175
+WeaponPower=20
+WeaponAttack=15
+Strength=15
+Experience=54000
+ArmourPower=18
+Sex=I
+
+[Dragon Highlord With Dragon]
+Dexterity=17
+GoldOnHand=15000
+Luck=19
+HitPoints=80
+WeaponPower=15
+WeaponAttack=13
+Strength=18
+Experience=14000
+ArmourPower=16
+Sex=I
+
+[Kitara & Skie]
+Dexterity=17
+GoldOnHand=12000
+Luck=16
+HitPoints=75
+WeaponPower=15
+WeaponAttack=16
+Strength=15
+Experience=9000
+ArmourPower=17
+Sex=I
+
+[Wyrmfather]
+Dexterity=18
+GoldOnHand=14000
+Luck=17
+HitPoints=90
+WeaponPower=17
+WeaponAttack=16
+Strength=18
+Experience=14000
+ArmourPower=18
+Sex=I
+
diff --git a/xtrn/dgnlance/monsters5.ini b/xtrn/dgnlance/monsters5.ini
new file mode 100644
index 0000000000000000000000000000000000000000..2ddc63232489312922bfc482ae817cedcb09426d
--- /dev/null
+++ b/xtrn/dgnlance/monsters5.ini
@@ -0,0 +1,36 @@
+[Lord Soth]
+Dexterity=23
+GoldOnHand=19000
+Luck=23
+HitPoints=385
+WeaponPower=17
+WeaponAttack=18
+Strength=23
+Experience=20550
+ArmourPower=17
+Sex=I
+
+[Thakisis]
+Dexterity=25
+GoldOnHand=60000
+Luck=25
+HitPoints=425
+WeaponPower=18
+WeaponAttack=18
+Strength=25
+Experience=98000
+ArmourPower=18
+Sex=I
+
+[Dalamar]
+Dexterity=23
+GoldOnHand=19000
+Luck=23
+HitPoints=385
+WeaponPower=17
+WeaponAttack=18
+Strength=23
+Experience=20550
+ArmourPower=17
+Sex=I
+
diff --git a/xtrn/dgnlance/player.js b/xtrn/dgnlance/player.js
new file mode 100644
index 0000000000000000000000000000000000000000..85889b234c943e9127f8371a3384014558552e2d
--- /dev/null
+++ b/xtrn/dgnlance/player.js
@@ -0,0 +1,1107 @@
+function supplant()
+{
+	return((random(40)+80)/100);
+}
+
+var Status = {
+	DEAD : (1<<0),
+	ONLINE : (1<<1),
+	PLAYER : (1<<2),
+	MONSTER : (1<<3),
+};
+
+var SexType = {
+	HE : 0,
+	HIS : 1,
+	HIM : 2,
+};
+
+function Player(name) {
+	if(name==undefined)
+		name=user.alias;
+	this.name=name;		// User name
+	this.pseudo=name;	// Game alias
+	this.killer="";		// Killed by if status==DEAD
+	this.bcry="";		// Battle cry
+	this.winmsg="";		// What the user says when he wins
+	this.gaspd="";		// Users dying curse
+	this.laston=system.datestr();		// Date last on
+	this.sex='M';
+	this.status=Status.DEAD;		// ALIVE, DEAD, PLAYER, MONSTER
+	this.flights=0;		// Number of times the user can play today
+	this.level=0;			// Level (???)
+	this.strength=0;
+	this.intelligence=0;
+	this.dexterity=0;
+	this.constitution=0;
+	this.charisma=0;
+	this.experience=0;
+	this.luck=0;
+	this.weapon=new Weapon("Hands",1,1,0);		// Weapon
+	this.armour=new Armour("Tunic",1,0);		// Armour
+	this.hps=0;			// Hitpoints
+	this.damage=0;		// Damage taken so far
+	this.gold=0;		// Gold on hand
+	this.bank=0;		// Gold in the bank
+	this.wins=0;		// Wins so far
+	this.losses=0;		// Losses so far
+	this.battles=0;		// Battles left today
+	this.fights=0;		// Fights left today
+    // Players variance... applied to various rolls, Generally, how good the
+    // player is feeling. Is set at start and not modified
+	this.vary=0;
+
+	this.his="his";
+	this.he="he";
+	this.him="him";
+	this.His="His";
+	this.He="He";
+	this.Him="Him";
+	this.load=Player_load;
+	this.save=Player_save;
+	this.statshow=Player_statshow;
+	this.levelupdate=Player_levelupdate;
+	this.chstats=Player_chstats;
+	this.depobank=Player_depobank;
+	this.withdrawbank=Player_withdrawbank;
+	this.heal=Player_heal;
+	this.vic=Player_changemessage;
+	this.create=Player_create;
+	this.gamble=Player_gamble;
+	this.training=Player_training;
+	this.leave=Player_leave;
+	this.battle=Player_battle;
+	this.tohit=Player_tohit;
+	this.damageroll=Player_damage;
+	this.changename=Player_changename;
+
+	this.__defineGetter__("his", function() {
+		if(this.charisma < 8)
+			return("its");
+		switch(this.sex) {
+			case 'F':
+				return("hers");
+			case 'M':
+				return("his");
+			default:
+				return("its");
+		}
+	});
+	
+	this.__defineGetter__("he", function() {
+		if(this.charisma < 8)
+			return("it");
+		switch(this.sex) {
+			case 'F':
+				return("she");
+			case 'M':
+				return("he");
+			default:
+				return("it");
+		}
+	});
+	
+	this.__defineGetter__("him", function() {
+		if(this.charisma < 8)
+			return("it");
+		switch(this.sex) {
+			case 'F':
+				return("her");
+			case 'M':
+				return("him");
+			default:
+				return("it");
+		}
+	});
+
+	this.__defineGetter__("His", function() {
+		if(this.charisma < 8)
+			return("Its");
+		switch(this.sex) {
+			case 'F':
+				return("Hers");
+			case 'M':
+				return("His");
+			default:
+				return("Its");
+		}
+	});
+	
+	this.__defineGetter__("He", function() {
+		if(this.charisma < 8)
+			return("It");
+		switch(this.sex) {
+			case 'F':
+				return("She");
+			case 'M':
+				return("He");
+			default:
+				return("It");
+		}
+	});
+	
+	this.__defineGetter__("Him", function() {
+		if(this.charisma < 8)
+			return("It");
+		switch(this.sex) {
+			case 'F':
+				return("Her");
+			case 'M':
+				return("Him");
+			default:
+				return("It");
+		}
+	});
+};
+
+function Player_statshow()
+{
+	console.clear();
+	console.attributes="M0";
+	/*console.*/writeln("Name: "+this.pseudo+"   Level: "+this.level);
+	console.attributes="HC0";
+	console.write("W/L: "+this.wins+"/"+this.losses);
+	/*console.*/writeln("   Exp: "+this.experience);
+	/*console.*/writeln();
+	console.attributes="HY0";
+	/*console.*/writeln("Steel  (in hand): "+this.gold);
+	/*console.*/writeln("Steel  (in bank): "+this.bank);
+	/*console.*/writeln();
+	console.attributes="HB0";
+	console.write("Battles: "+this.battles);
+	console.write("   Flights: "+this.flights);
+	console.write("   Fights: "+this.fights);
+	/*console.*/writeln("   HPs: "+(this.hps-this.damage)+"("+this.hps+")");
+	/*console.*/writeln();
+	console.attributes="HC0";
+	console.write("Weapon: "+this.weapon.name);
+	/*console.*/writeln("     Armor: "+this.armour.name);
+}
+
+function Player_load(filename)
+{
+	if(filename==undefined)
+		filename=getpath()+"players.ini";
+	var players=new File(filename);
+	var item_name;
+	var item_cost;
+	var item_power;
+	var item_attack;
+
+	if(!Lock(players.name, bbs.node_num, false, 1)) {
+		/*console.*/writeln();
+		/*console.*/writeln("Cannot lock "+players.name+" for read!");
+		/*console.*/writeln();
+		console.pause();
+		return(false);
+	}
+	if(!players.open("r", true)) {
+		Unlock(players.name);
+		return(false);
+	}
+
+	this.pseudo=players.iniGetValue(this.name, "Alias", this.name);		// Game alias
+	this.killer=players.iniGetValue(this.name, "Killer", "");		// Killed by if status==DEAD
+	this.bcry=players.iniGetValue(this.name, "BattleCry", "");		// Battle cry
+	this.winmsg=players.iniGetValue(this.name, "WinMessage", "");		// What the user says when he wins
+	this.gaspd=players.iniGetValue(this.name, "DyingCurse", "");		// Users dying curse
+	this.laston=players.iniGetValue(this.name, "LastOn", system.datestr());		// Date last on
+	this.sex=players.iniGetValue(this.name, "Sex", "M");
+	this.status=players.iniGetValue(this.name, "Status", Status.DEAD);		// ALIVE, DEAD, PLAYER, MONSTER
+	this.flights=players.iniGetValue(this.name, "Flights", 0);		// Number of times the user can play today
+	this.level=players.iniGetValue(this.name, "Level", 0);			// Level (???)
+	this.strength=players.iniGetValue(this.name, "Strength", 0);
+	this.intelligence=players.iniGetValue(this.name, "Intelligence", 0);
+	this.dexterity=players.iniGetValue(this.name, "Dexterity", 0);
+	this.constitution=players.iniGetValue(this.name, "Constitution", 0);
+	this.charisma=players.iniGetValue(this.name, "Charisma", 0);
+	this.experience=players.iniGetValue(this.name, "Experience", 0);
+	this.luck=players.iniGetValue(this.name, "Luck", 0);
+
+	item_name=players.iniGetValue(this.name, "Weapon", "Hands");		// Weapon
+	item_attack=players.iniGetValue(this.name, "WeaponAttack", 1);		// Weapon attack
+	item_power=players.iniGetValue(this.name, "WeaponPower", 1);		// Weapon power
+	item_cost=players.iniGetValue(this.name, "WeaponCost", 0);		// Weapon power
+	this.weapon=new Weapon(item_name, item_attack, item_power, item_cost);
+
+	item_name=players.iniGetValue(this.name, "Armour", "Tunic");		// Armour index
+	item_power=players.iniGetValue(this.name, "ArmourPower", 1);		// Weapon power
+	item_cost=players.iniGetValue(this.name, "ArmourCost", 0);		// Weapon power
+	this.armour=new Armour(item_name, item_power, item_cost);
+
+	this.hps=players.iniGetValue(this.name, "HitPoints", 0);			// Hitpoints
+	this.damage=players.iniGetValue(this.name, "Damage", 0);		// Damage taken so far
+	this.gold=players.iniGetValue(this.name, "GoldOnHand", 0);		// Gold on hand
+	this.bank=players.iniGetValue(this.name, "GoldInBank", 0);		// Gold in the bank
+	this.wins=players.iniGetValue(this.name, "Wins", 0);		// Wins so far
+	this.losses=players.iniGetValue(this.name, "Losses", 0);		// Losses so far
+	this.battles=players.iniGetValue(this.name, "Battles", 0);		// Battles left today
+	this.fights=players.iniGetValue(this.name, "Fights", 0);		// Fights left today
+    // Players variance... applied to various rolls, Generally, how good the
+    // player is feeling. Is set at start and not modified
+	this.vary=players.iniGetValue(this.name, "Vary", 0.8);
+	if(this.hps-this.damage <=0)
+		this.status |= Status.DEAD;
+	players.close();
+	Unlock(players.name);
+
+	return(true);
+}
+
+function Player_save(name)
+{
+	var players=new File(getpath()+"players.ini");
+
+	if(!Lock(players.name, bbs.node_num, true, 1)) {
+		/*console.*/writeln();
+		/*console.*/writeln("Cannot lock "+players.name+" for write!");
+		/*console.*/writeln();
+		console.pause();
+		return(false);
+	}
+	if(!players.open(file_exists(players.name) ? 'r+':'w+')) {
+		Unlock(players.name);
+		return(false);
+	}
+
+	players.iniSetValue(this.name, "Alias", this.pseudo);		// Game alias
+	players.iniSetValue(this.name, "Killer", this.killer);		// Killed by if status==DEAD
+	players.iniSetValue(this.name, "BattleCry", this.bcry);		// Battle cry
+	players.iniSetValue(this.name, "WinMessage", this.winmsg);		// What the user says when he wins
+	players.iniSetValue(this.name, "DyingCurse", this.gaspd);		// Users dying curse
+	players.iniSetValue(this.name, "LastOn", this.laston);		// Date last on
+	players.iniSetValue(this.name, "Sex", this.sex);
+	players.iniSetValue(this.name, "Status", this.status);		// ALIVE, DEAD, PLAYER, MONSTER
+	players.iniSetValue(this.name, "Flights", this.flights);		// Number of times the user can play today
+	players.iniSetValue(this.name, "Level", this.level);			// Level (???)
+	players.iniSetValue(this.name, "Strength", this.strength);
+	players.iniSetValue(this.name, "Intelligence", this.intelligence);
+	players.iniSetValue(this.name, "Dexterity", this.dexterity);
+	players.iniSetValue(this.name, "Constitution", this.constitution);
+	players.iniSetValue(this.name, "Charisma", this.charisma);
+	players.iniSetValue(this.name, "Experience", this.experience);
+	players.iniSetValue(this.name, "Luck", this.luck);
+	players.iniSetValue(this.name, "Weapon", this.weapon.name);		// Weapon index
+	players.iniSetValue(this.name, "WeaponAttack", this.weapon.attack);		// Weapon attack
+	players.iniSetValue(this.name, "WeaponPower", this.weapon.power);		// Weapon power
+	players.iniSetValue(this.name, "WeaponCost", this.weapon.cost);		// Weapon cost
+	players.iniSetValue(this.name, "Armour", this.armour.name);		// Armour index
+	players.iniSetValue(this.name, "ArmourPower", this.armour.power);		// Armour index
+	players.iniSetValue(this.name, "ArmourCost", this.armour.cost);		// Armour index
+	players.iniSetValue(this.name, "HitPoints", this.hps);			// Hitpoints
+	players.iniSetValue(this.name, "Damage", this.damage);		// Damage taken so far
+	players.iniSetValue(this.name, "GoldOnHand", this.gold);		// Gold on hand
+	players.iniSetValue(this.name, "GoldInBank", this.bank);		// Gold in the bank
+	players.iniSetValue(this.name, "Wins", this.wins);		// Wins so far
+	players.iniSetValue(this.name, "Losses", this.losses);		// Losses so far
+	players.iniSetValue(this.name, "Battles", this.battles);		// Battles left today
+	players.iniSetValue(this.name, "Fights", this.fights);		// Fights left today
+    // Players variance... applied to various rolls, Generally, how good the
+    // player is feeling. Is set at start and not modified
+	players.iniSetValue(this.name, "Vary", this.vary);
+	players.close();
+	Unlock(players.name);
+	return(true);
+}
+
+function Player_levelupdate()
+{
+	if(this.experience > required[this.level+1]) {
+		this.level++;
+		console.attributes="HY0";
+		/*console.*/writeln("Welcome to level "+this.level+"!");
+		x=random(6)+1;
+		switch(random(6)) {
+			case 0:
+				this.strength++;
+				break;
+			case 1:
+				this.intelligence++;
+				break;
+			case 2:
+				this.luck++;
+				break;
+			case 3:
+				this.dexterity++;
+				break;
+			case 4:
+				this.constitution++;
+				break;
+			case 5:
+				this.charisma++;
+				break;
+		}
+		this.hps = parseInt(this.hps + random(5) + 1 + (this.constitution / 4));
+	}
+}
+
+function Player_chstats()
+{
+	function incre(this_obj)
+	{
+		console.write("Increase which stat? ");
+		switch(dgn_getkeys("123456Q")) {
+			case '1':
+				/*console.*/writeln("Strength");
+				this_obj.strength++;
+				break;
+			case '2':
+				/*console.*/writeln("Intelligence");
+				this_obj.intelligence++;
+				break;
+			case '3':
+				/*console.*/writeln("Dexterity");
+				this_obj.dexterity++;
+				break;
+			case '4':
+				/*console.*/writeln("Luck");
+				this_obj.luck++;
+				break;
+			case '5':
+				/*console.*/writeln("Constitution");
+				this_obj.constitution++;
+				break;
+			case '6':
+				/*console.*/writeln("Charisma");
+				this_obj.charisma++;
+				break;
+			case 'Q':
+				/*console.*/writeln("Quit");
+				return(false);
+		}
+		return(true);
+	}
+
+	function decre(this_obj)
+	{
+		console.write("Decrease which stat? ");
+		switch(dgn_getkeys("123456Q")) {
+			case '1':
+				/*console.*/writeln("Strength");
+				this_obj.strength--;
+				break;
+			case '2':
+				/*console.*/writeln("Intelligence");
+				this_obj.intelligence--;
+				break;
+			case '3':
+				/*console.*/writeln("Dexterity");
+				this_obj.dexterity--;
+				break;
+			case '4':
+				/*console.*/writeln("Luck");
+				this_obj.luck--;
+				break;
+			case '5':
+				/*console.*/writeln("Constitution");
+				this_obj.constitution--;
+				break;
+			case '6':
+				/*console.*/writeln("Charisma");
+				this_obj.charisma--;
+				break;
+			case 'Q':
+				/*console.*/writeln("Quit");
+				return(false);
+		}
+		return(true);
+	}
+
+	function ministat(this_obj)
+	{
+		var valid=true;
+		var orig=new Object();
+
+		function check(value, name) {
+			if(value < 6) {
+				valid=false;
+				/*console.*/writeln();
+				/*console.*/writeln(name+" cannot go below 6");
+			}
+		}
+
+		function restore(this_obj) {
+			this_obj.strength=orig.strength;
+			this_obj.intelligence=orig.intelligence;
+			this_obj.dexterity=orig.dexterity;
+			this_obj.luck=orig.luck;
+			this_obj.constitution=orig.constitution;
+			this_obj.charisma=orig.charisma;
+		}
+
+		orig.strength=this_obj.strength;
+		orig.intelligence=this_obj.intelligence;
+		orig.dexterity=this_obj.dexterity;
+		orig.luck=this_obj.luck;
+		orig.constitution=this_obj.constitution;
+		orig.charisma=this_obj.charisma;
+
+		/*console.*/writeln();
+		/*console.*/writeln("Status Change:");
+		/*console.*/writeln("^^^^^^^^^^^^^^");
+		/*console.*/writeln("1> Str: "+(this_obj.strength));
+		/*console.*/writeln("2> Int: "+(this_obj.intelligence));
+		/*console.*/writeln("3> Dex: "+(this_obj.dexterity));
+		/*console.*/writeln("4> Luk: "+(this_obj.luck));
+		/*console.*/writeln("5> Con: "+(this_obj.constitution));
+		/*console.*/writeln("6> Chr: "+(this_obj.charisma));
+		/*console.*/writeln();
+		check(this_obj.strength,"Strength");
+		check(this_obj.intelligence,"Intelligence");
+		check(this_obj.dexterity,"Dexterity");
+		check(this_obj.luck,"Luck");
+		check(this_obj.constitution,"Constitution");
+		check(this_obj.charisma,"Charisma");
+		if(valid) {
+			console.write("Is this correct? ");
+			if(dgn_getkeys("YN")=='Y') {
+				/*console.*/writeln("Yes");
+				return(true);
+			}
+			else {
+				/*console.*/writeln("No");
+				restore(this_obj);
+				return(false);
+			}
+		}
+		restore(this_obj);
+		return(false);
+	}
+
+	console.clear();
+	while(1) {
+		/*console.*/writeln("Status Change:");
+		/*console.*/writeln("@@@@@@@@@@@@@@");
+		/*console.*/writeln("You may increase any stat by one,");
+		/*console.*/writeln("yet you must decrease another by two.");
+		/*console.*/writeln();
+		/*console.*/writeln("1> Str: "+this.strength);
+		/*console.*/writeln("2> Int: "+this.intelligence);
+		/*console.*/writeln("3> Dex: "+this.dexterity);
+		/*console.*/writeln("4> Luk: "+this.luck);
+		/*console.*/writeln("5> Con: "+this.constitution);
+		/*console.*/writeln("6> Chr: "+this.charisma);
+		/*console.*/writeln();
+		if(incre(this)) {
+			if(decre(this)) {
+				if(ministat(this))
+					break;
+			}
+		}
+		else
+			break;
+	}
+}
+
+function Player_depobank()
+{
+	var tmp=this.gold;
+	this.gold -= tmp;
+	this.bank += tmp;
+	/*console.*/writeln();
+	console.attributes="HC0";
+	/*console.*/writeln(this.bank+" Steel pieces are in the bank.");
+}
+
+function Player_withdrawbank()
+{
+	var tmp=this.bank;
+	this.gold += tmp;
+	this.bank -= tmp;
+	/*console.*/writeln();
+	console.attributes="HC0";
+	/*console.*/writeln("You are now carrying "+this.gold+" Steel pieces.");
+}
+
+function Player_heal()
+{
+	var opt;
+
+	console.clear();
+	console.attributes="M0";
+	/*console.*/writeln("Clerics want "+(8*this.level)+" Steel pieces per wound.");
+	console.attributes="HY0";
+	/*console.*/writeln("You have "+this.damage+" points of damage to heal.");
+	console.attributes="HC0";
+	console.write("How many points do you want healed? ");
+	// TODO: We need max as default an some way to cancel...
+	opt=console.getnum(this.damage);
+	if((opt*this.level*8) > this.gold) {
+		console.attributes="HR0";
+		/*console.*/writeln("Sorry, you do not have enough Steel.");
+		opt=0;
+	}
+	else if (opt > this.damage)
+		opt = this.damage;
+	this.damage -= opt;
+	this.gold -= 8*opt*this.level;
+	/*console.*/writeln(opt+" hit points healed.");
+}
+
+function Player_changemessage()
+{
+	function getmessage(prompt, msg)
+	{
+		while(1) {
+			/*console.*/writeln();
+			console.attributes="HC0";
+			/*console.*/writeln(prompt);
+			console.write("> ");
+			msg=console.getstr(msg, 77, K_EDIT|K_AUTODEL|K_LINE);
+			console.write("Is this correct? ");
+			if(dgn_getkeys("YN")=='Y') {
+				/*console.*/writeln("Yes");
+				return(msg);
+			}
+			/*console.*/writeln("No");
+		}
+	}
+
+	this.bcry=getmessage("Enter your new Battle Cry.", this.bcry);
+	this.gaspd=getmessage("What will you say when you're mortally wounded?", this.gaspd);
+	this.winmsg=getmessage("What will you say when you win?", this.winmsg);
+}
+
+function Player_create(isnew)
+{
+	this.vary=supplant();
+	this.strength=12;
+	this.status=Status.ONLINE;
+	this.intelligence=12;
+	this.luck=12;
+	this.damage=0;
+	this.dexterity=12;
+	this.constitution=12;
+	this.charisma=12;
+	this.gold=random(100)+175;
+	this.weapon=new Weapon("Hands", 1, 1, 0);
+	this.armour=new Armour("Tunic", 1, 0);
+	this.experience=0;
+	this.bank=random(199)+1;
+	this.level=1;
+	this.hps=random(4)+1+this.constitution;
+	this.wins=0;
+	this.loses=0;
+	this.sex='M';
+	if(isnew) {
+		this.bcry="";
+		this.gaspd="";
+		this.winmsg="";
+		/*console.*/writeln();
+		this.pseudo=user.alias;
+		this.vic();
+		this.battles = Config.BATTLES_PER_DAY;
+		this.fights = Config.FIGHTS_PER_DAY;
+		this.flights = Config.FLIGHTS_PER_DAY;
+	}
+	console.write("What sex would you like your character to be? (M/F) ");
+	this.sex=dgn_getkeys("MF");
+	/*console.*/writeln();
+}
+
+function Player_gamble()
+{
+	var realgold=0;
+	var okea=0;
+
+	if(this.fighs==0)
+		/*console.*/writeln("The Shooting Gallery is closed until tomorrow!");
+	else {
+		console.clear();
+		/*console.*/writeln("  Welcome to the Shooting Gallery");
+		/*console.*/writeln(" Maximum wager is 25,000 Steel pieces");
+		/*console.*/writeln();
+		console.attributes="HY0";
+		/*console.*/writeln("How many Steel pieces do you wish to wager? ");
+		console.attributes="W0";
+		realgold=console.getnum(25000);
+		if(realgold > this.gold) {
+			/*console.*/writeln();
+			/*console.*/writeln("You do not have enough Steel!");
+		}
+		if(realgold != 0 && this.gold >= realgold && realgold <= 25000 && realgold >= 1) {
+			okea=random(99)+1;
+			if(okea <= 3) {
+				realgold *= 100;
+				this.gold += realgold;
+				/*console.*/writeln("You shot all the targets and win "+realgold+" Steel pieces!");
+			}
+			else if (okea <= 15) {
+				realgold *= 10;
+				this.gold += realgold;
+				/*console.*/writeln("You shot 50% of the targets and win "+realgold+" Steel pieces!");
+			}
+			else if (okea <= 30) {
+				realgold *= 3;
+				this.gold += realgold;
+				/*console.*/writeln("You shot 25% of the targets and win "+realgold+" Steel pieces!");
+			}
+			else {
+				this.gold -= realgold;
+				/*console.*/writeln("Sorry, You Hath Lost!");
+			}
+		}
+	}
+}
+
+function Player_training()
+{
+	const upcost=1000000;
+
+	function dotrain(this_obj, attr)
+	{
+		/*console.*/writeln(attr);
+		console.write("Are you sure? ");
+		if(dgn_getkeys("YN")=='Y') {
+			/*console.*/writeln("Yes");
+			this_obj.gold -= upcost;
+			return(1);
+		}
+		/*console.*/writeln("No");
+		return(0);
+	}
+
+	if(this.fights < 1)
+		/*console.*/writeln("The Training Grounds are closed until tomorrow!");
+	else {
+		console.clear();
+		/*console.*/writeln("Training Grounds");
+		/*console.*/writeln("%%%%%%%%%%%%%%%%");
+		/*console.*/writeln("Each characteristic you wish to upgrade");
+		/*console.*/writeln("will cost 1,000,000 Steel pieces per point.");
+		/*console.*/writeln();
+		console.write("Do you wish to upgrade a stat? ");
+		if(dgn_getkeys("YN")=='Y') {
+			/*console.*/writeln("Yes");
+			if(this.gold < upcost)
+				/*console.*/writeln("Sorry, but you do not have enough Steel!");
+			else {
+				/*console.*/writeln();
+				/*console.*/writeln("1> Strength       2> Intelligence");
+				/*console.*/writeln("3> Dexterity      4> Luck");
+				/*console.*/writeln("5> Constitution   5> Charisma");
+				/*console.*/writeln();
+				console.attributes="HY0";
+				console.write("Which stat do you wish to increase? ");
+				console.attributes="W0";
+				switch(console.getnum(6)) {
+					case 1:
+						this.strength+=dotrain(this, "Strength");
+						break;
+					case 2:
+						this.intelligence+=dotrain(this, "Intelligence");
+						break;
+					case 3:
+						this.dexterity+=dotrain(this, "Dexterity");
+						break;
+					case 4:
+						this.luck+=dotrain(this, "Luck");
+						break;
+					case 5:
+						this.constitution+=dotrain(this, "Constitution");
+						break;
+					case 6:
+						this.charisma+=dotrain(this, "Charisma");
+						break;
+				}
+			}
+		}
+		else
+			/*console.*/writeln("No");
+	}
+}
+
+function Player_leave()
+{
+	this.status &= ~(Status.ONLINE);
+	this.save();
+}
+
+function Player_tohit(opp)
+{
+	return((this.weapon.attack*this.strength*this.dexterity*(random(5)+1)*this.vary)
+		/ (opp.armour.power*opp.dexterity*opp.luck*opp.vary));
+}
+
+function Player_damage(opp)
+{
+	return(parseInt((this.weapon.power*this.strength*(random(5)+1)*(random(5)+1)*this.vary)
+		/ (opp.armour.power*opp.luck*opp.vary)));
+}
+
+function Player_battle(opp)
+{
+	var option;
+
+	function endofbattle(this_obj, winner,loser)
+	{
+		var lstr,wstr;
+		var logfile=new File(getpath()+"today.log");
+
+		if(this_obj==winner) {
+			won=true;
+			lstr=loser.his;
+			wstr="You";
+		}
+		else {
+			won=false;
+			wstr=loser.his;
+			lstr="your";
+		}
+		if(opp.status==Status.MONSTER)
+			opp.gold=opp.gold * supplant();
+		/*console.*/writeln();
+		if(won && opp.gold > 0)
+			/*console.*/writeln("You take "+opp.his+" "+opp.gold+" Steel pieces.");
+		else {
+			if(opp.status != Status.MONSTER && this_obj.gold > 0)
+				/*console.*/writeln(opp.He+" takes your "+this_obj.gold+" Steel pieces");
+		}
+		winner.gold += loser.gold;
+		loser.gold = 0;
+		if(opp.status != Status.MONSTER) {
+			/*console.*/writeln();
+			console.attributes="G0";
+			if(won) {
+				/*console.*/writeln("The Last Words "+loser.he+" utters are...");
+				/*console.*/writeln();
+				/*console.*/writeln(opp.gaspd);
+				/*console.*/writeln();
+			}
+			else {
+				/*console.*/writeln("The Last Words You Hear Are...");
+				/*console.*/writeln();
+				/*console.*/writeln(opp.winmsg);
+				/*console.*/writeln();
+			}
+			winner.wins++;
+			loser.losses++;
+			loser.killer=winner.pseudo;
+			loser.status|=Status.DEAD;
+			if(loser.weapon.attack+loser.weapon.power
+					> winner.weapon.attack+winner.weapon.power) {
+				var tmpweap=loser.weapon;
+
+				loser.weapon=winner.weapon;
+				winner.weapon=tmpweap;
+				console.attributes="G0";
+				/*console.*/writeln(wstr+" Hath Taken "+lstr+" Weapon.");
+			}
+			if(loser.armour.power > winner.armour.power) {
+				var tmparm=loser.armour;
+
+				loser.armour=winner=armour;
+				winner.armour=tmparm;
+				console.attributes="HY0";
+				/*console.*/writeln(wstr+" Hath Taken "+lstr+" Armour.");
+			}
+			if(Lock(logfile.name, bbs.node_num, true, 1)) {
+				if(logfile.open("a",true)) {
+					logfile.writeln(system.datestr()+system.timestr()+": "+this_obj.pseudo+" attacked "+opp.pseudo+" and "+winner.pseudo+" was victorious!");
+					logfile.close();
+				}
+				Unlock(logfile.name);
+			}
+			else {
+				/*console.*/writeln();
+				/*console.*/writeln("Cannot lock "+logfile.name+" for write!");
+				/*console.*/writeln();
+				console.pause();
+			}
+		}
+		opp.experience *= supplant();
+		winner.experience += opp.experience;
+		if(won || opp.status != Status.MONSTER)
+			/*console.*/writeln(wstr+" obtain "+opp.experience+" exp points.");
+		if(!(opp.status & Status.MONSTER))
+			opp.save();
+	}
+
+	function findo(this_obj)
+	{
+		var rnd;
+	
+		/*console.*/writeln();
+		console.attributes="HY0";
+		/*console.*/writeln("The Vile Enemy Dropped Something!");
+		console.write("Do you want to get it? ");
+		if(dgn_getkeys("YN")=='Y') {
+			/*console.*/writeln("Yes");
+			rnd=random(100)+1;
+			if(rnd<10) {
+				var i;
+				for(i=1; i<weapon.length; i++) {
+					if(weapon[i].attack+weapon[i].power > this_obj.weapon.attack+this_obj.weapon.power) {
+						/*console.*/writeln("You have found a "+weapon[i].name+".");
+						this_obj.weapon=new Weapon(weapon[i].name, weapon[i].attack, weapon[i].power, weapon[i].cost);
+						break;
+					}
+				}
+				if(i>=weapon.length) {
+					/*console.*/writeln("It's gone!!!");
+				}
+				// TODO: Next weapon!
+			}
+			else if(rnd < 40) {
+				this_obj.gold += 40;
+				/*console.*/writeln("You have come across 40 Steel pieces");
+			}
+			else {
+				/*console.*/writeln("It's gone!!!!");
+			}
+		}
+		else {
+			/*console.*/writeln("No");
+			/*console.*/writeln("I wonder what it was?!?");
+		}
+	}
+
+	function amode(this_obj)
+	{
+		var roll;
+
+		roll=this_obj.tohit(opp);
+		if(roll<1.5) {
+			switch(random(4)) {
+				case 0:
+					/*console.*/writeln("Swish you missed!");
+					break;
+				case 1:
+					/*console.*/writeln("HA HA! "+opp.he+" dodges your swing!");
+					break;
+				case 2:
+					/*console.*/writeln("CLANG, The attack is blocked");
+					break;
+				case 3:
+					/*console.*/writeln("You Fight vigorously and miss!");
+					break;
+			}
+		}
+		else {
+			roll=this_obj.damageroll(opp);
+			if(roll > 5*this_obj.power)
+				roll=5*this_obj.power;
+			if(roll < 1)
+				roll=1;
+			opp.damage += roll;
+			switch(random(3)) {
+				case 0:
+					/*console.*/writeln(format("You sliced %s for %1.0f.",opp.him,roll));
+					break;
+				case 1:
+					/*console.*/writeln(format("You made contact to %s body for %1.0f.",opp.his,roll));
+					break;
+				case 2:
+					/*console.*/writeln(format("You hacked %s for %1.0f.",opp.him,roll));
+					break;
+			}
+			if(opp.hps <= opp.damage) {
+				/*console.*/writeln();
+				switch(random(4)) {
+					case 0:
+						/*console.*/writeln("A Painless Death!");
+						break;
+					case 1:
+						/*console.*/writeln(opp.He+" Had died!");
+						break;
+					case 2:
+						/*console.*/writeln("A Smooth killing!");
+						break;
+					case 3:
+						/*console.*/writeln(opp.He+" has gone to the Abyss!");
+						break;
+				}
+				if(random(100)<30)
+					findo(this_obj);
+				endofbattle(this_obj,this_obj,opp);
+			}
+		}
+	}
+
+	function bmode(this_obj)
+	{
+		var roll;
+		
+		if(opp.hps > opp.damage && this_obj.damage < this_obj.hps) {
+			roll=opp.tohit(this_obj);
+			if(roll < 1.5) {
+				console.attributes="G0";
+				/*console.*/writeln(opp.His+" attack tears your armour.");
+			}
+			else {
+				roll=opp.damageroll(this_obj);
+				if(roll > 5*opp.power)
+					roll=5*opp.power;
+				if(roll<1)
+					roll=1;
+				switch(random(3)) {
+					case 0:
+						/*console.*/writeln(format("%s hammered you for %1.0f",opp.He,roll));
+						break;
+					case 1:
+						/*console.*/writeln(format("%s swung and hit for %1.0f",opp.He,roll));
+						break;
+					case 2:
+						/*console.*/writeln(format("You are surprised when %s hits you for %1.0f",opp.he,roll));
+						break;
+				}
+				this_obj.damage += roll;
+				if(this_obj.damage >= this_obj.hps) {
+					/*console.*/writeln();
+					switch(random(4)) {
+						case 0:
+							/*console.*/writeln("Return This Knight To Huma's Breast....");
+							break;
+						case 1:
+							/*console.*/writeln("You Hath Been Slain!!");
+							break;
+						case 2:
+							/*console.*/writeln("Return Soon Brave Warrior!");
+							break;
+						case 3:
+							/*console.*/writeln("May Palidine Be With You!");
+							break;
+					}
+					endofbattle(this_obj,opp,this_obj);
+				}
+			}
+		}
+	}
+
+	function attackmodes(this_obj)
+	{
+		if(opp.dexterity > this_obj.dexterity) {
+			if(this_obj.damage < this_obj.hps && opp.damage < opp.hps)
+				bmode(this_obj);
+			if(this_obj.damage < this_obj.hps && opp.damage < opp.hps)
+				amode(this_obj);
+		}
+		else {
+			if(this_obj.damage < this_obj.hps && opp.damage < opp.hps)
+				amode(this_obj);
+			if(this_obj.damage < this_obj.hps && opp.damage < opp.hps)
+				bmode(this_obj);
+		}
+	}
+
+	while(this.damage < this.hps && opp.damage < opp.hps) {
+		/*console.*/writeln();
+		console.attributes="HY0";
+		/*console.*/writeln("You are attacked by a "+opp.pseudo);
+		for(option='?'; option=='?'; ) {
+			console.attributes="HB0";
+			console.write("Combat ("+(this.hps-this.damage)+"): (B,F,S): ");
+			option=dgn_getkeys("BFS?");
+			if(option=="?") {
+				/*console.*/writeln("Help");
+				/*console.*/writeln();
+				/*console.*/writeln();
+				/*console.*/writeln("(B)attle your opponent.");
+				/*console.*/writeln("(F)lee from your opponent.");
+				/*console.*/writeln("(S)tatus check");
+			}
+		}
+		switch(option) {
+			case 'B':
+				/*console.*/writeln("Battle");
+				attackmodes(this);
+				break;
+			case 'S':
+				/*console.*/writeln("Stats");
+				this.statshow();
+				break;
+			case 'F':
+				/*console.*/writeln("Flee");
+				if(random(4)+1 + this.dexterity > opp.dexterity) {
+					/*console.*/writeln();
+					console.attributes="G0";
+					/*console.*/writeln("You Ride away on a Silver Dragon.");
+					return;
+				}
+				else {
+					console.attributes="G0";
+					/*console.*/writeln("You cannot escape!.");
+					bmode(this);
+				}
+				break;
+		}
+	}
+}
+
+function Player_changename()
+{
+	var oldpseudo=this.pseudo;
+
+	/*console.*/writeln();
+	console.attributes="HC0";
+	/*console.*/writeln("Your family crest has been stolen, they");
+	/*console.*/writeln("inscribe a new one with the name...");
+	console.write("> ");
+	this.pseudo=console.getstr(this.pseudo, 30, K_EDIT|K_AUTODEL|K_LINE);
+	/*console.*/writeln();
+	/*console.*/write("Are you sure? ");
+	if(dgn_getkeys("YN")=='Y') {
+		// TODO: No duplicate names!
+		if(this.pseudo=='')
+			this.pseudo=oldpseudo;
+		/*console.*/writeln("Yes");
+	}
+	else {
+		/*console.*/writeln("No");
+		this.pseudo=oldpseudo;
+	}
+}
+
+function getplayerlist(filename)
+{
+	function sortlist(a, b)
+	{
+		var asum,bsum;
+
+		if(a.level > b.level)
+			return(-1);
+		if(b.level > a.level)
+			return(1);
+		asum=a.wins-a.losses;
+		bsum=b.wins-b.losses;
+		if(asum > bsum)
+			return(-1);
+		if(bsum > asum)
+			return(1);
+		return(0);
+	}
+
+	if(filename==undefined)
+		filename=getpath()+"players.ini";
+	var players=new File(filename);
+	var list=new Array();
+
+	if(!Lock(players.name, bbs.node_num, false, 1)) {
+		/*console.*/writeln();
+		/*console.*/writeln("Cannot lock "+players.name+" for read!");
+		/*console.*/writeln();
+		console.pause();
+		return(list);
+	}
+	if(!players.open("r", true)) {
+		Unlock(players.name);
+		/*console.*/writeln();
+		/*console.*/writeln("Cannot open "+players.name+" for read!");
+		/*console.*/writeln();
+		console.pause();
+		return(list);
+	}
+	var all=players.iniGetSections();
+	players.close();
+	Unlock(players.name);
+
+	while(all.length) {
+		var newplayer=new Player(all.shift());
+		newplayer.load(filename);
+		list.push(newplayer);
+	}
+
+	list.sort(sortlist);
+
+	return(list);
+}
diff --git a/xtrn/dgnlance/plug.asc b/xtrn/dgnlance/plug.asc
new file mode 100644
index 0000000000000000000000000000000000000000..1ff38674db419a1557d870b52abb9dff8267329f
--- /dev/null
+++ b/xtrn/dgnlance/plug.asc
@@ -0,0 +1,23 @@
+                                  CALL
+
+����Ŀڿ ڿ���Ŀ       ����Ŀ���Ŀ ڿ       ڿ���Ŀ����Ŀ       ���Ŀ���Ŀ
+�Ŀ��ٳ� �������       �Ŀ��ٳ�Ŀ� ��       ������ٳ  O �       ��Ŀ������
+  ��  ���ٳ��Ŀ          ��  �� �� ��  / \  ����Ŀ ����\\       �� �����
+  ��  ��Ŀ�����          ��  �� �� ��/ / \ \������ ��  ��       �� �����
+  ��  �� �����Ŀ         ��  ���ٳ � /     \ ����Ŀ��  ��       ���ٳ��
+  ��  �� �������         ��  ����� ��       ���������  ��       �������
+
+
+ڿ ڿ ��Ŀ ���Ŀ ڿ ڿ    ����Ŀ ����Ŀ ����Ŀ �����Ŀ ����Ŀ ����Ŀ ڿ     ڿ
+�� �� ���� ����� �� ��    ������ ���Ŀ� �  O � ������� ������ �  O � \\    //
+���ٳ  ��  ��    ���ٳ    ����Ŀ ��  �� ����\\ ��      ��Ŀ   ����\\  \\  //
+��Ŀ�  ��  �� ڿ ��Ŀ�    ���Ŀ� ��  �� ��  �� ��      ����   ��  ��    ��
+�� �� ���� ���ٳ �� ��    ����ٳ ����ٳ ��  �� �����Ŀ ����Ŀ ��  ��    ��
+�� �� ���� ����� �� ��    ������ ������ ��  �� ������� ������ ��  ��    ��
+               �
+               �
+���������������۰�����������������������������������������������������\
+���������������۱�����������������������������������������������������/
+               �                                               �   �
+�m             �            1200 - 9600 Baud                    � �           .
+                             717-696-2236
diff --git a/xtrn/dgnlance/weapon.js b/xtrn/dgnlance/weapon.js
new file mode 100644
index 0000000000000000000000000000000000000000..09f07813fb3bf3ea5205bce4282cdaf36fe1598d
--- /dev/null
+++ b/xtrn/dgnlance/weapon.js
@@ -0,0 +1,43 @@
+function Weapon(name, attack, power, cost)
+{
+	this.name=name;
+	this.attack=attack;
+	this.power=power;
+	this.cost=cost;
+}
+
+// Read in the weapon list...
+function sortweaponlist(a, b)
+{
+	var asum,bsum;
+
+	asum=a.attack+a.power;
+	bsum=b.attack+b.power;
+	if(asum < bsum)
+		return(-1);
+	if(bsum < asum)
+		return(1);
+	return(0);
+}
+
+var weaponfile=new File(getpath()+"weapons.ini");
+var weapon=new Array();
+
+if(weaponfile.open("r", true)) {
+	var all=weaponfile.iniGetSections();
+
+	while(all.length) {
+		var name=all.shift();
+		var attack=weaponfile.iniGetValue(name, "Attack", 1);
+		var power=weaponfile.iniGetValue(name, "Power", 1);
+		var cost=weaponfile.iniGetValue(name, "Cost", 0);
+		weapon.push(new Weapon(name,attack,power,cost));
+	}
+	weapon.sort(sortweaponlist);
+}
+else {
+	console.attributes="HIR0";
+	/*console.*/writeln();
+	/*console.*/writeln("Cannot open weapons file!");
+	/*console.*/writeln();
+}
diff --git a/xtrn/dgnlance/weapons.ini b/xtrn/dgnlance/weapons.ini
new file mode 100644
index 0000000000000000000000000000000000000000..f4cf7ac189f278554e8c50894032407008cbd34b
--- /dev/null
+++ b/xtrn/dgnlance/weapons.ini
@@ -0,0 +1,129 @@
+[Hands]
+Attack=1
+Power=1
+Cost=0
+
+[Dagger]
+Attack=2
+Power=2
+Cost=100
+
+[Club]
+Attack=3
+Power=3
+Cost=200
+
+[Short Sword]
+Attack=4
+Power=4
+Cost=400
+
+[Axe]
+Attack=4
+Power=5
+Cost=800
+
+[Longsword]
+Attack=5
+Power=5
+Cost=1000
+
+[Bow]
+Attack=6
+Power=6
+Cost=2000
+
+[Crossbow]
+Attack=7
+Power=7
+Cost=4000
+
+[Short Sword +1]
+Attack=8
+Power=8
+Cost=6000
+
+[Battle Axe]
+Attack=9
+Power=9
+Cost=8000
+
+[Longsword +1]
+Attack=10
+Power=10
+Cost=10000
+
+[Magic Sword]
+Attack=11
+Power=11
+Cost=20000
+
+[Dagger +3]
+Attack=12
+Power=12
+Cost=40000
+
+[Mace]
+Attack=13
+Power=13
+Cost=60000
+
+[Morning Star]
+Attack=14
+Power=14
+Cost=80000
+
+[Magic Missle]
+Attack=15
+Power=15
+Cost=100000
+
+[Potion of Fire Breath]
+Attack=16
+Power=16
+Cost=200000
+
+[Magic Scroll]
+Attack=17
+Power=17
+Cost=400000
+
+[Spell Book]
+Attack=18
+Power=18
+Cost=600000
+
+[Wyrmslayer]
+Attack=19
+Power=19
+Cost=800000
+
+[Staff of Maginus]
+Attack=20
+Power=20
+Cost=1000000
+
+[Frost Reaver]
+Attack=21
+Power=21
+Cost=2000000
+
+[Tharkan Axe]
+Attack=22
+Power=22
+Cost=4000000
+
+[Hammer of Kharas]
+Attack=23
+Power=23
+Cost=8000000
+
+[Huma's Blade]
+Attack=24
+Power=24
+Cost=10000000
+
+[Dragonlance]
+Attack=25
+Power=25
+Cost=0