diff --git a/xtrn/gttrivia/gttrivia.ini b/xtrn/gttrivia/gttrivia.ini
index 9adeff4e5d99842039bcd1ecb07c0334f50a700e..f4f514718e5826444f8721f9754a49053594e330 100644
--- a/xtrn/gttrivia/gttrivia.ini
+++ b/xtrn/gttrivia/gttrivia.ini
@@ -2,6 +2,10 @@
 numQuestionsPerPlay=30
 numTriesPerQuestion=4
 maxNumPlayerScoresToDisplay=10
+; scoresMsgSubBoardsForPosting specifies a comma-separated list of internal sub-board
+; codes for sub-boards to post user scores in, as a backup in case the server
+; specified in the REMOTE_SERVER section can't be reached
+scoresMsgSubBoardsForPosting=
 
 [COLORS]
 error=YH
@@ -31,5 +35,11 @@ dirty_minds=AGE 18
 server=digitaldistortionbbs.com
 port=10088
 
+; The SERVER section is for hosting game scores only
 [SERVER]
 deleteScoresOlderThanDays=182
+; scoresMsgSubBoardsForReading specifies a comma-separated list of internal sub-board
+; codes for sub-boards to read user scores from. To use this, set up an event in
+; SCFG > External Programs > Timed Events to run gttrivia.js with the command-line
+; parameter -read_scores_from_subboard
+scoresMsgSubBoardsForReading=
diff --git a/xtrn/gttrivia/gttrivia.js b/xtrn/gttrivia/gttrivia.js
index 1921b51d0acf0fb2e4364f76b36d625aec0f8ba4..a206a25405d1b307ba397a878eeb5ce5759999e1 100644
--- a/xtrn/gttrivia/gttrivia.js
+++ b/xtrn/gttrivia/gttrivia.js
@@ -11,6 +11,10 @@ Date       Author            Description
                              also sysop functions to remove players and users from the hosted
                              inter-BBS scores. Also, answer clues now don't mask spaces in the
                              answer.
+2022-12-08 Eric Oulashin     Version 1.02
+                             The game can now post scores in (networked) message sub-boards as
+                             a backup to using a JSON DB server in case the server can't be
+                             contacted.							 
 */
 
 
@@ -37,11 +41,8 @@ if (system.version_num < 31500)
 }
 
 // Version information
-var GAME_VERSION = "1.01";
-var GAME_VER_DATE = "2022-11-25";
-// Version of data written to the server, if applicable.  This might not necessarily be the same as
-// the version of the game.
-var SERVER_DATA_VERSION = "1.01";
+var GAME_VERSION = "1.02";
+var GAME_VER_DATE = "2022-12-08";
 
 // Determine the location of this script (its startup directory).
 // The code for figuring this out is a trick that was created by Deuce,
@@ -141,18 +142,91 @@ var JSON_DB_LOCK_UNLOCK = -1;
 
 
 
-// Enable debugging if the first command-line parameter is -debug
-var gDebug = false;
-if (argv.length > 0)
-	gDebug = (argv[0].toUpperCase() == "-DEBUG");
+// Load the settings from the .ini file
+var gSettings = loadSettings(gStartupPath);
 
+// Parse command-line arguments
+var gCmdLineArgs = parseCmdLineArgs(argv);
 
-// Display the program logo
-displayProgramLogo(true, false);
+// If the command-line argument was specified to post or read scores in the configured message
+// sub-board, then do so and exit.
+if (gCmdLineArgs.postScoresToSubBoard)
+{
+	if (gSettings.behavior.scoresMsgSubBoardsForPosting.length == 0)
+	{
+		log(LOG_ERR, format("%s - Post scores to sub-boards specified, but scoresMsgSubBoardsForPosting is not set", GAME_NAME));
+		exit(2);
+	}
 
-// Load the settings from the .ini file
-var gSettings = loadSettings(gStartupPath);
+	var exitCode = 0;
+	for (var i = 0; i < gSettings.behavior.scoresMsgSubBoardsForPosting.length; ++i)
+	{
+		var subCode = gSettings.behavior.scoresMsgSubBoardsForPosting[i];
+		if (!msg_area.sub.hasOwnProperty(subCode))
+		{
+			log(LOG_ERR, format("%s - Sub-board-code %s does not exist (specified in %s)", GAME_NAME, subCode, "scoresMsgSubBoardsForPosting"));
+			exitCode = 3;
+			continue;
+		}
 
+		var postSuccessful = postGTTriviaScoresToSubBoard(subCode);
+		// For logging
+		var subBoardInfoStr = msg_area.sub[subCode].name + " - " + msg_area.sub[subCode].description;
+		// Write the status to the log
+		var logMsg = "";
+		var logLevel = LOG_INFO;
+		if (postSuccessful)
+			logMsg = format("%s - Successfully posted local scores to sub-board %s (%s)", GAME_NAME, subCode, subBoardInfoStr);
+		else
+		{
+			logLevel = LOG_ERR;
+			logMsg = format("%s - Posting scores to sub-board %s (%s) failed!", GAME_NAME, subCode, subBoardInfoStr);
+			exitCode = 3;
+		}
+		log(logLevel, logMsg);
+	}
+	exit(exitCode);
+}
+else if (gCmdLineArgs.readScoresFromSubBoard)
+{
+	if (gSettings.server.scoresMsgSubBoardsForReading.length == 0)
+	{
+		log(LOG_ERR, format("%s - Read scores from sub-boards specified, but scoresMsgSubBoardsForReading is not set", GAME_NAME));
+		exit(2);
+	}
+
+	var exitCode = 0;
+	for (var i = 0; i < gSettings.server.scoresMsgSubBoardsForReading.length; ++i)
+	{
+		var subCode = gSettings.server.scoresMsgSubBoardsForReading[i];
+		if (subCode.length == 0 || !msg_area.sub.hasOwnProperty(subCode))
+		{
+			log(LOG_ERR, format("%s - Invalid sub-board code specified in scoresMsgSubBoardsForReading: %s", GAME_NAME, subCode));
+			continue;
+		}
+
+		var readSuccessful = readGTTriviaScoresFromSubBoard(subCode);
+		// For logging
+		var subBoardInfoStr = msg_area.sub[subCode].name + " - " + msg_area.sub[subCode].description;
+		// Write the status to the log
+		var logMsg = "";
+		var logLevel = LOG_INFO;
+		if (readSuccessful)
+			logMsg = format("%s - Successfully read scores from sub-board %s (%s)", GAME_NAME, subCode, subBoardInfoStr);
+		else
+		{
+			logLevel = LOG_ERR;
+			logMsg = format("%s - Reading scores from sub-board %s (%s) failed!", GAME_NAME, subCode, subBoardInfoStr);
+			exitCode = 4;
+		}
+		log(logLevel, logMsg);
+	}
+	exit(exitCode);
+}
+
+
+// Display the program logo
+displayProgramLogo(true, false);
 
 //console.clear("\x01n");
 
@@ -296,7 +370,6 @@ function playTrivia()
 				console.attributes = "N" + gSettings.colors.clue;
 				console.print(partiallyHiddenStr(QAArray[i].answer, tryI-1) + "\x01n");
 				console.crlf();
-				
 			}
 			// Prompt for an answer
 			console.attributes = "N" + gSettings.colors.answerPrompt;
@@ -360,8 +433,50 @@ function playTrivia()
 	console.crlf();
 	console.print("\x01b\x01hUpdating the scores file...");
 	console.crlf();
-	updateScoresFile(userPoints, qaFilenameInfo[chosenSectionIdx].sectionName);
-	console.print("Done.\x01n");
+	// Update the local scores file
+	var updateLocalScoresRetObj = updateScoresFile(userPoints, qaFilenameInfo[chosenSectionIdx].sectionName);
+	if (updateLocalScoresRetObj.succeeded)
+	{
+		// If there is a server configured, then send the user's score to the server too.
+		// If there are no server settings configured, or posting scores to the server fails,
+		// then if there's a sub-board configured, then write the user scores to the sub-board
+		var writeUserScoresToSubBoard = false;
+		if (gSettings.hasValidServerSettings())
+		{
+			writeUserScoresToSubBoard = !updateScoresOnServer(user.alias, updateLocalScoresRetObj.userScoresObj);
+			if (writeUserScoresToSubBoard)
+			{
+				var errorMsg = "\x01n" + attrCodeStr(gSettings.colors.error) + "Failed to update scores on the remote server.";
+				if (gSettings.behavior.scoresMsgSubBoardsForPosting.length > 0)
+					errorMsg += " Will post server scores in message area(s); server scores will be delayed.\x01n";
+				console.putmsg(errorMsg, P_WORDWRAP|P_NOATCODES);
+				console.attributes = "BH"; // As before
+			}
+		}
+		else
+			writeUserScoresToSubBoard = true;
+		if (writeUserScoresToSubBoard)
+		{
+			// If there are any message sub-boards configured, post the scores in there
+			for (var i = 0; i < gSettings.behavior.scoresMsgSubBoardsForPosting.length; ++i)
+			{
+				var subCode = gSettings.behavior.scoresMsgSubBoardsForPosting[i];
+				if (msg_area.sub.hasOwnProperty(subCode))
+				{
+					if (postGTTriviaScoresToSubBoard(subCode))
+						log(LOG_INFO, format("%s - Successfully posted scores in the sub-board", GAME_NAME));
+					else
+						log(LOG_INFO, format("%s - Posting scores in the sub-board failed!", GAME_NAME));
+				}
+			}
+		}
+		console.print("Done.\x01n");
+	}
+	else
+	{
+		console.attributes = "N" + gSettings.colors.error;
+		console.print("Failed to save the scores!\x01n");
+	}
 	console.crlf();
 	return 0;
 }
@@ -384,6 +499,7 @@ function loadSettings(pStartupPath)
 		settings.colors = iniFile.iniGetObject("COLORS");
 		settings.category_ars = iniFile.iniGetObject("CATEGORY_ARS");
 		settings.remoteServer = iniFile.iniGetObject("REMOTE_SERVER");
+		settings.server = iniFile.iniGetObject("SERVER");
 
 		// Ensure the actual expected setting name & color names exist in the settings
 		if (typeof(settings.behavior) !== "object")
@@ -394,6 +510,8 @@ function loadSettings(pStartupPath)
 			settings.category_ars = {};
 		if (typeof(settings.remoteServer) !== "object")
 			settings.remoteServer = {};
+		if (typeof(settings.server) !== "object")
+			settings.server = {};
 
 		if (typeof(settings.behavior.numQuestionsPerPlay) !== "number")
 			settings.behavior.numQuestionsPerPlay = 10;
@@ -440,7 +558,10 @@ function loadSettings(pStartupPath)
 			settings.colors.clue = "GH";
 		if (typeof(settings.colors.answerAfterIncorrect) !== "string")
 			settings.colors.answerAfterIncorrect = "G";
-		
+
+		settings.behavior.scoresMsgSubBoardsForPosting = splitAndVerifyMsgSubCodes(settings.behavior.scoresMsgSubBoardsForPosting, "scoresMsgSubBoardsForPosting");
+		settings.server.scoresMsgSubBoardsForReading = splitAndVerifyMsgSubCodes(settings.server.scoresMsgSubBoardsForReading, "scoresMsgSubBoardsForReading");
+
 		// Sanity checking
 		if (settings.behavior.numQuestionsPerPlay <= 0)
 			settings.behavior.numQuestionsPerPlay = 10;
@@ -465,11 +586,7 @@ function loadSettings(pStartupPath)
 	settings.remoteServer.gtTriviaScope = "GTTRIVIA";
 	// JSON location: For the BBS name, use the QWK ID if available, but if not, use the system name and replace spaces
 	// with underscores (since spaces may cause issues in JSON property names)
-	var BBS_ID = "";
-	if (system.qwk_id.length > 0)
-		BBS_ID = system.qwk_id;
-	else
-		BBS_ID = system.name.replace(/ /g, "_");
+	var BBS_ID = getBBSIDForJSON();
 	settings.remoteServer.scoresJSONLocation = "SCORES";
 	settings.remoteServer.BBSJSONLocation = settings.remoteServer.scoresJSONLocation + ".systems." + BBS_ID;
 	settings.remoteServer.userScoresJSONLocationWithoutUsername = settings.remoteServer.BBSJSONLocation + ".user_scores";
@@ -505,6 +622,39 @@ function genFullPathCfgFilename(pFilename, pDefaultPath)
 	}
 	return fullyPathedFilename;
 }
+// Takes a comma-separated list of internal sub-board codes and splits them into an array,
+// and also verifies they exist; the returned array will contain only ones that exist.
+// Also ensures there are no duplicates in the array.
+//
+// Parameters:
+//  pSubCodeList: A comma-separated list of message sub-board codes (string)
+//  pSettingName: Optional string representing the configuration setting name, for logging
+//                invalid sub-board codes. If this is missing/null or empty, no logging will be done.
+function splitAndVerifyMsgSubCodes(pSubCodeList, pSettingName)
+{
+	if (typeof(pSubCodeList) !== "string")
+		return [];
+
+	var settingName = (typeof(pSettingName) === "string" ? pSettingName : "");
+
+	var subCodes = [];
+	var subCodesFromList = pSubCodeList.split(",");
+	for (var i = 0; i < subCodesFromList.length; ++i)
+	{
+		if (msg_area.sub.hasOwnProperty(subCodesFromList[i]))
+		{
+			if (!subCodes.indexOf(subCodesFromList[i]) > -1)
+				subCodes.push(subCodesFromList[i]);
+		}
+		else if (settingName.length > 0)
+		{
+			var errMsg = format("%s - For configuration setting %s, %s is an invalid sub-board code", GAME_NAME, settingName, subCodesFromList[i]);
+			log(LOG_ERR, errMsg);
+		}
+	}
+	//!msg_area.sub.hasOwnProperty(
+	return subCodes;
+}
 
 // Displays the program logo
 //
@@ -814,10 +964,19 @@ function levenshteinDistance(pStr1, pStr2)
 // Parameters:
 //  pUserCurrentGameScore: The user's score for their current game
 //  pLastSectionName: The name of the last trivia section the user played
+//
+// Return value: An object with the following properties:
+//               succeeded: Boolean: Whether or not saving the scores to the file succeeded
+//               userScoresObj: An object containing information on the user's scores
 function updateScoresFile(pUserCurrentGameScore, pLastSectionName)
 {
+	var retObj = {
+		succeeded: false,
+		userScoresObj: {}
+	};
+
 	if (typeof(pUserCurrentGameScore) !== "number")
-		return false;
+		return retObj;
 
 	var lastSectionName = (typeof(pLastSectionName) === "string" ? pLastSectionName : "");
 
@@ -858,8 +1017,7 @@ function updateScoresFile(pUserCurrentGameScore, pLastSectionName)
 	if (typeof(scoresObj) !== "object")
 		scoresObj = {};
 
-	var scoresForUser = {}; // Will store just the current user's score information
-
+	retObj.succeeded = true;
 	// Add/update the user's score, and save the scores file
 	try
 	{
@@ -939,10 +1097,11 @@ function updateScoresFile(pUserCurrentGameScore, pLastSectionName)
 		scoresObj[user.alias].last_score = pUserCurrentGameScore;
 		scoresObj[user.alias].last_trivia_category = lastSectionName;
 		scoresObj[user.alias].last_time = currentTime;
-		scoresForUser = scoresObj[user.alias];
+		retObj.userScoresObj = scoresObj[user.alias];
 	}
 	catch (error)
 	{
+		retObj.succeeded = false;
 		console.print("* Line " + error.lineNumber + ": " + error);
 		console.crlf();
 		log(LOG_ERR, GAME_NAME + " - Updating trivia score object: Line " + error.lineNumber + ": " + error);
@@ -954,13 +1113,13 @@ function updateScoresFile(pUserCurrentGameScore, pLastSectionName)
 		scoresFile.write(JSON.stringify(scoresObj));
 		scoresFile.close();
 	}
+	else
+		retObj.succeeded = false;
 
 	// Delete the semaphore file
 	file_remove(SCORES_SEMAPHORE_FILENAME);
 
-	// If there is a server configured, then send the user's score to the server too
-	if (gSettings.hasValidServerSettings())
-		updateScoresOnServer(user.alias, scoresForUser);
+	return retObj;
 }
 
 // Updates user scores on the server (if there is one configured)
@@ -968,35 +1127,54 @@ function updateScoresFile(pUserCurrentGameScore, pLastSectionName)
 // Parameters:
 //  pUserNameForScores: The user's name as used for the scores
 //  pUserScoreInfo: An object containing user scores, as created by updateScoresFile()
+//
+// Return value: Boolean: Whether or not the update was successful
 function updateScoresOnServer(pUserNameForScores, pUserScoreInfo)
 {
 	// Make sure the settings have valid server settings and the user score info object is valid
 	if (!gSettings.hasValidServerSettings())
-		return;
+		return false;
 	if (typeof(pUserNameForScores) !== "string" || pUserNameForScores.length == 0 || typeof(pUserScoreInfo) !== "object")
-		return;
+		return false;
 
+	var updateSuccessful = true;
 	try
 	{
+		// You could lock for each individual write like this:
+		//
+		// var JSONLocation = gSettings.remoteServer.BBSJSONLocation + ".bbs_name";
+		// jsonClient.write(gSettings.remoteServer.gtTriviaScope, JSONLocation, system.name, JSON_DB_LOCK_WRITE);
+		//
+		// You can also call lock() to lock the JSON location you want to use, do your reads & writes, and then
+		// unlock at the end.  The code here locks on the BBS ID JSON location and does its writes, so that
+		// readGTTriviaScoresFromSubBoard() can also lock on the same location to do its writes when importing
+		// scores from the messagebase.
+
 		var jsonClient = new JSONClient(gSettings.remoteServer.server, gSettings.remoteServer.port);
+		jsonClient.lock(gSettings.remoteServer.gtTriviaScope, gSettings.remoteServer.BBSJSONLocation, JSON_DB_LOCK_WRITE);
 		// Ensure the BBS name on the server has been set
 		var JSONLocation = gSettings.remoteServer.BBSJSONLocation + ".bbs_name";
-		jsonClient.write(gSettings.remoteServer.gtTriviaScope, JSONLocation, system.name, JSON_DB_LOCK_WRITE);
+		jsonClient.write(gSettings.remoteServer.gtTriviaScope, JSONLocation, system.name);
 		// Write the scores on the server
 		JSONLocation = gSettings.remoteServer.userScoresJSONLocationWithoutUsername + "." + pUserNameForScores;
-		jsonClient.write(gSettings.remoteServer.gtTriviaScope, JSONLocation, pUserScoreInfo, JSON_DB_LOCK_WRITE);
+		jsonClient.write(gSettings.remoteServer.gtTriviaScope, JSONLocation, pUserScoreInfo);
 		// Write the client & version information in the user scores too
 		var gameInfo = format("%s version %s (%s)", GAME_NAME, GAME_VERSION, GAME_VER_DATE);
-		jsonClient.write(gSettings.remoteServer.gtTriviaScope, JSONLocation + ".game_client", gameInfo, JSON_DB_LOCK_WRITE);
+		JSONLocation += ".game_client";
+		jsonClient.write(gSettings.remoteServer.gtTriviaScope, JSONLocation, gameInfo);
+		// Now that we're done, unlock and disconnect
+		jsonClient.unlock(gSettings.remoteServer.gtTriviaScope, gSettings.remoteServer.BBSJSONLocation);
 		jsonClient.disconnect();
 	}
 	catch (error)
 	{
+		updateSuccessful = false;
 		console.print("* Line " + error.lineNumber + ": " + error);
 		console.crlf();
 		log(LOG_ERR, GAME_NAME + " - Updating scores on server: Line " + error.lineNumber + ": " + error);
 		bbs.log_str(GAME_NAME + " - Updating scores on server: Line " + error.lineNumber + ": " + error);
 	}
+	return updateSuccessful;
 }
 
 // Shows the saved scores - First the locally saved scores, and then if there is a
@@ -1125,7 +1303,7 @@ function showServerScores()
 				showUserScoresArray(sortedScores, data.systems[BBS_ID].bbs_name);
 				// If debugging is enabled, then also show the game_client property (game_client stores the name
 				// & version of the game that wrote the user score data for this player)
-				if (gDebug)
+				if (gCmdLineArgs.debug)
 				{
 					if (data.systems[BBS_ID].user_scores[playerName].hasOwnProperty("game_client"))
 					{
@@ -1165,7 +1343,7 @@ function showUserScoresArray(pUserScoresArray, pBBSName)
 	// Make the format string for printf()
 	var scoreWidth = 6;
 	var dateWidth = 10;
-	var categoryWidth = 15;
+	var categoryWidth = 25; //15;
 	var nameWidth = 0;
 	var formatStr = "";
 	if (console.screen_columns >= 80)
@@ -1558,4 +1736,295 @@ function doSysopMenu()
 			}
 		}
 	}
-}
\ No newline at end of file
+}
+
+// Returns a BBS ID to use for JSON (the QWK ID if existing; otherwise, the BBS name with
+// spaces converted to underscores)
+function getBBSIDForJSON()
+{
+	var BBS_ID = "";
+	if (system.qwk_id.length > 0)
+		BBS_ID = system.qwk_id;
+	else
+		BBS_ID = system.name.replace(/ /g, "_");
+	return BBS_ID;
+}
+
+// Posts all users' scores from the local scores file to a message sub-board
+//
+// Parameters:
+//  pSubCode: The internal code of the sub-board to post the scores to
+function postGTTriviaScoresToSubBoard(pSubCode)
+{
+	if (typeof(pSubCode) !== "string" || !msg_area.sub.hasOwnProperty(pSubCode))
+		return false;
+
+	// Prepare the user scores for posting in the message sub-board
+	// JSON location: For the BBS name, use the QWK ID if available, but if not, use the system name and replace spaces
+	// with underscores (since spaces may cause issues in JSON property names)
+	var BBS_ID = getBBSIDForJSON();
+	var scoresForThisBBS = {};
+	scoresForThisBBS[BBS_ID] = {};
+	scoresForThisBBS[BBS_ID].bbs_name = system.name;
+	scoresForThisBBS[BBS_ID].user_scores = {};
+
+	// Read the scores file to see if the user has an existing score in there already
+	var scoresFile = new File(SCORES_FILENAME);
+	if (file_exists(SCORES_FILENAME))
+	{
+		if (scoresFile.open("r"))
+		{
+			var scoreFileArray = scoresFile.readAll();
+			scoresFile.close();
+			var scoreFileContents = "";
+			for (var i = 0; i < scoreFileArray.length; ++i)
+				scoreFileContents += (scoreFileArray[i] + "\n");
+			try
+			{
+				scoresForThisBBS[BBS_ID].user_scores = JSON.parse(scoreFileContents);
+			}
+			catch (error)
+			{
+				scoresForThisBBS[BBS_ID].user_scores = {};
+				log(LOG_ERR, GAME_NAME + " - Loading scores: Line " + error.lineNumber + ": " + error);
+				bbs.log_str(GAME_NAME + " - Loading scores: Line " + error.lineNumber + ": " + error);
+			}
+		}
+	}
+	if (typeof(scoresForThisBBS[BBS_ID]) !== "object")
+		scoresForThisBBS[BBS_ID].user_scores = {};
+
+	if (Object.keys(scoresForThisBBS[BBS_ID].user_scores).length === 0)
+		return false;
+
+	var postSuccessful = false;
+	var dataMsgbase = new MsgBase(pSubCode);
+	if (dataMsgbase.open())
+	{
+		// Create the message header, and send the message.
+		var header = {
+			to: GAME_NAME, // "Good Time Trivia"
+			from: system.username(1),
+			from_ext: 1,
+			subject: system.name
+			//from_net_type: NET_NONE,
+			//to_net_type: NET_NONE
+		};
+		/*
+		if ((dataMsgbase.settings & SUB_QNET) == SUB_QNET)
+		{
+			header.from_net_type = NET_QWK;
+			header.to_net_type = NET_QWK;
+		}
+		else if ((dataMsgbase.settings & SUB_PNET) == SUB_PNET)
+		{
+			header.from_net_type = NET_POSTLINK;
+			header.to_net_type = NET_POSTLINK;
+		}
+		else if ((dataMsgbase.settings & SUB_FIDO) == SUB_FIDO)
+		{
+			header.from_net_type = NET_FIDO;
+			header.to_net_type = NET_FIDO;
+		}
+		else if ((dataMsgbase.settings & SUB_INET) == SUB_INET)
+		{
+			header.from_net_type = NET_INTERNET;
+			header.to_net_type = NET_INTERNET;
+		}
+		*/
+
+		//postSuccessful = dataMsgbase.save_msg(header, JSON.stringify(scoresForThisBBS));
+		var message = lfexpand(JSON.stringify(scoresForThisBBS, null, 1));
+		message += " --- " + GAME_NAME + " " + GAME_VERSION + " (" + GAME_VER_DATE + ")";
+		postSuccessful = dataMsgbase.save_msg(header, message);
+
+		dataMsgbase.close();
+	}
+	return postSuccessful;
+}
+
+// Reads trivia scores from a sub-board and posts on the host system (if configured)
+//
+// Parameters:
+//  pSubCode: An internal code of a sub-board to read the game scores from
+//
+// Return value: Boolean - Whether or not the score update succeeded
+function readGTTriviaScoresFromSubBoard(pSubCode)
+{
+	if (typeof(pSubCode) !== "string" || !msg_area.sub.hasOwnProperty(pSubCode))
+		return false;
+
+	// For logging
+	var subBoardInfoStr = msg_area.sub[subCode].name + " - " + msg_area.sub[subCode].description;
+	log(LOG_INFO, format("%s - Reading score posts from sub-board %s (%s)", GAME_NAME, pSubCode, subBoardInfoStr));
+
+	// For posting to the local JSON server, get the configured JSON service port number
+	var localJSONServicePort = getJSONSvcPortFromServicesIni();
+	if (localJSONServicePort <= 0)
+	{
+		log(LOG_ERR, format("%s - Local JSON service port is invalid (%d)", GAME_NAME, localJSONServicePort));
+		return false;
+	}
+
+	var scoreUpdateSucceeded = true;
+	var dataMsgbase = new MsgBase(pSubCode);
+	if (dataMsgbase.open())
+	{
+		try
+		{
+			// Create the JSON Client object for updating the scores on the local JSON DB server.
+			// For each user score in the JSON object, if their last time is after the current last
+			// time in the server's JSON, then post the user's score.
+			var jsonClient = new JSONClient("127.0.0.1", localJSONServicePort);
+
+			var to_crc = crc16_calc(GAME_NAME.toLowerCase());
+			var index = dataMsgbase.get_index();
+			for (var i = 0; index && i < index.length; i++)
+			{
+				var idx = index[i];
+				if ((idx.attr & MSG_DELETE) == MSG_DELETE || idx.to != to_crc)
+					continue;
+
+				var msgHdr = dataMsgbase.get_msg_header(true, idx.offset);
+				if (!msgHdr)
+					continue;
+				if (/*!msgHdr.from_net_type ||*/ msgHdr.to != GAME_NAME)
+					continue;
+
+				var msgBody = dataMsgbase.get_msg_body(msgHdr, false, false, false);
+				if (msgBody == null || msgBody.length == 0) //if (!msgBody)
+					continue;
+
+				log(LOG_INFO, "Scores message imported at " + strftime("%Y-%m-%d %H:%M:%S", msgHdr.when_imported_time));
+				// Clean up the message body so that it only has JSON
+				var txtIdx = msgBody.indexOf(" --- " + GAME_NAME);
+				if (txtIdx > 0)
+					msgBody = msgBody.substr(0, txtIdx);
+				// Parse the JSON from the message, and then go through the BBSes and users
+				// in it.  For any user scores that are more recent than what's on the server,
+				// post those to the server.
+				try
+				{
+					var scoresObjFromMsg = JSON.parse(msgBody);
+					// For each user score, if their last time is after the current last time in the
+					// server's JSON, then post the user's score.
+					for (var BBS_ID in scoresObjFromMsg)
+					{
+						// Lock on the BBS name location in the JSON, do the writes, and unlock when we're done
+						jsonClient.lock(gSettings.remoteServer.gtTriviaScope, gSettings.remoteServer.BBSJSONLocation, JSON_DB_LOCK_WRITE);
+						// Ensure the BBS name on the server has been set
+						var JSONLocation = gSettings.remoteServer.scoresJSONLocation + ".systems." + BBS_ID + ".bbs_name";
+						jsonClient.write(gSettings.remoteServer.gtTriviaScope, JSONLocation, system.name);
+						for (var userID in scoresObjFromMsg[BBS_ID].user_scores)
+						{
+							// For logging
+							var msgLastTimeFormatted = strftime("%Y-%m-%d %H:%M:%S", scoresObjFromMsg[BBS_ID].user_scores[userID].last_time);
+							var serverLastTimeFormatted = "";
+
+							// Read the current user's scores from the server and compare the user's last_time
+							// from the message in the sub-board with the one from the server, and only update
+							// if newer.
+							JSONLocation = gSettings.remoteServer.scoresJSONLocation + ".systems." + BBS_ID + ".user_scores." + userID;
+							var serverUserScoreData = jsonClient.read(gSettings.remoteServer.gtTriviaScope, JSONLocation);
+							var postUserScoresToServer = false;
+							if (typeof(serverUserScoreData) === "object")
+							{
+								postUserScoresToServer = (scoresObjFromMsg[BBS_ID].user_scores[userID].last_time > serverUserScoreData.last_time);
+								serverLastTimeFormatted = strftime("%Y-%m-%d %H:%M:%S", serverUserScoreData.last_time)
+							}
+							else
+							{
+								postUserScoresToServer = true;
+								serverLastTimeFormatted = "N/A";
+							}
+
+							// Log the user, BBS, and date of the scores seen
+							var logMsg = format("%s - Saw scores for %s on %s; in message: %s, on server: %s; will update server scores: %s",
+												GAME_NAME, userID, scoresObjFromMsg[BBS_ID].bbs_name, msgLastTimeFormatted, serverLastTimeFormatted,
+												postUserScoresToServer);
+							log(LOG_INFO, logMsg);
+
+							// If the scores from the message are newer, write the scores on the server
+							if (postUserScoresToServer)
+							{
+								JSONLocation = gSettings.remoteServer.scoresJSONLocation + ".systems." + BBS_ID + ".user_scores." + userID;
+								jsonClient.write(gSettings.remoteServer.gtTriviaScope, JSONLocation, scoresObjFromMsg[BBS_ID].user_scores[userID]);
+							}
+							// Now that we've written the user scores, unlock this BBS in the JSON
+							jsonClient.unlock(gSettings.remoteServer.gtTriviaScope, gSettings.remoteServer.BBSJSONLocation);
+						}
+					}
+				}
+				catch (error)
+				{
+					scoreUpdateSucceeded = false;
+					console.print("* Line " + error.lineNumber + ": " + error);
+					console.crlf();
+					log(LOG_ERR, GAME_NAME + " - Updating scores on server: Line " + error.lineNumber + ": " + error);
+					bbs.log_str(GAME_NAME + " - Updating scores on server: Line " + error.lineNumber + ": " + error);
+				}
+			}
+
+			jsonClient.disconnect();
+		}
+		catch (error)
+		{
+			scoreUpdateSucceeded = false;
+			console.print("* Line " + error.lineNumber + ": " + error);
+			console.crlf();
+			log(LOG_ERR, GAME_NAME + " - Connecting to JSON DB server (for scores update): Line " + error.lineNumber + ": " + error);
+			bbs.log_str(GAME_NAME + " - Connecting to JSON DB server (for scores update): Line " + error.lineNumber + ": " + error);
+		}
+
+		dataMsgbase.close();
+	}
+	else
+	{
+		var errMsg = format("%s - Unable to open sub-board %s (%s)", GAME_NAME, pSubCode, subBoardInfoStr);
+		log(LOG_ERR, errMsg);
+	}
+
+	log(LOG_INFO, format("%s - End of reading score posts from sub-board %s (%s).  All succeeded: %s", GAME_NAME, pSubCode,
+	                     subBoardInfoStr, scoreUpdateSucceeded));
+
+	return scoreUpdateSucceeded;
+}
+
+// Parses command-line arguments.  Returns an object with settings/actions specified.
+//
+// Parameters:
+//  argv: The array of command-line arguments
+//
+// Return value: An object with the following properties:
+//  debug: Boolean: Whether or not to enable debugging
+//  postScoresToSubBoard: Boolean: Whether or not to post scores in the configured sub-board. If this is
+//                        enabled, scores are to be posted and then the script should exit.
+//  readScoresFromSubBoard: Boolean: Whether or not to read scores from the configured sub-board.
+//                          If this is enabled, scores are to be posted and then the script should exit.
+function parseCmdLineArgs(argv)
+{
+	var retObj = {
+		debug: false,
+		postScoresToSubBoard: false,
+		readScoresFromSubBoard: false
+	};
+
+	if (!Array.isArray(argv))
+		return retObj;
+
+	var postScoresToSubOpt = "POST_SCORES_TO_SUBBOARD";
+	var readScoresFromSubOpt = "READ_SCORES_FROM_SUBBOARD";
+	for (var i = 0; i < argv.length; ++i)
+	{
+		var argUpper = argv[i].toUpperCase();
+		if (argUpper == "DEBUG" || argUpper == "-DEBUG" || argUpper == "--DEBUG")
+			retObj.debug = true;
+		else if (argUpper == postScoresToSubOpt || argUpper == "-" + postScoresToSubOpt || argUpper == "--" + postScoresToSubOpt)
+			retObj.postScoresToSubBoard = true;
+		else if (argUpper == readScoresFromSubOpt || argUpper == "-" + readScoresFromSubOpt || argUpper == "--" + readScoresFromSubOpt)
+			retObj.readScoresFromSubBoard = true;
+	}
+
+	return retObj;
+}
+
diff --git a/xtrn/gttrivia/qa/converter.js b/xtrn/gttrivia/qa/converter.js
index 8193ffa004d3b581a375bec2f42a0a359e8255d4..f418f9d74a02996b89070c0c7e2332727239a87c 100644
--- a/xtrn/gttrivia/qa/converter.js
+++ b/xtrn/gttrivia/qa/converter.js
@@ -1,15 +1,36 @@
 require("sbbsdefs.js", "K_NOCRLF");
 
 
-var inputFilename = "/mnt/data/SharedMedia/triviaQuestions/music_and_movies.txt";
-var outputFilename = inputFilename + "-converted.txt";
+var opts = parseCmdLine(argv);
 
 print("");
-print("Converting " + inputFilename);
+
+if (opts.inputFilename.length == 0)
+{
+	print("No input filename was specified.");
+	print("");
+	exit(1);
+}
+if (!file_exists(opts.inputFilename))
+{
+	print("Specified file does not exist:");
+	print(opts.inputFilename);
+	print("");
+	exit(2);
+}
+
+print("Input filename:" + opts.inputFilename + ":");
+print("");
+
+
+var outputFilename = opts.inputFilename + "-converted.txt";
+
+print("");
+print("Converting " + opts.inputFilename);
 print("Output: " + outputFilename);
 print("");
 
-var inFile = new File(inputFilename);
+var inFile = new File(opts.inputFilename);
 var outFile = new File(outputFilename);
 if (inFile.open("r"))
 {
@@ -112,7 +133,10 @@ if (inFile.open("r"))
 	inFile.close();
 }
 else
-	print("* Failed to open " + inputFilename + " for reading!");
+{
+	print("* Failed to open " + opts.inputFilename + " for reading!");
+	exit(3);
+}
 
 
 
@@ -127,4 +151,35 @@ function QA(pQuestion, pAnswer, pNumPoints)
 	this.question = pQuestion;
 	this.answer = pAnswer;
 	this.numPoints = pNumPoints;
+}
+
+// Parses command line options
+function parseCmdLine(argv)
+{
+	var retObj = {
+		inputFilename: ""
+	};
+
+	if (!Array.isArray(argv))
+		return retObj;
+
+	for (var i = 0; i < argv.length; ++i)
+	{
+		if (argv[i].length == 0) continue;
+		if (argv[i].charAt(0) == "-")
+		{
+			if (i >= argv.length - 1) continue;
+			var paramNameUpper = argv[i].substr(1).toUpperCase();
+			if (paramNameUpper == "INPUTFILENAME" || paramNameUpper == "INPUT_FILENAME")
+				retObj.inputFilename = argv[i+1];
+			++i; // To avoid analyzing the next parameter, since the next one is the value for this one
+		}
+		else
+		{
+			if (i == 0)
+				retObj.inputFilename = argv[i];
+		}
+	}
+
+	return retObj;
 }
\ No newline at end of file
diff --git a/xtrn/gttrivia/qa/general.qa b/xtrn/gttrivia/qa/general.qa
index ad94809b98ee7db459681d2136f8a7fc3b992d01..db0eb50f0b4a682d43fe8fd9266a80be810774ce 100644
--- a/xtrn/gttrivia/qa/general.qa
+++ b/xtrn/gttrivia/qa/general.qa
@@ -174,7 +174,7 @@ What is often seen as the smallest unit of memory?
 Kilobyte
 10
 
-Which planet is the hottest in the solar system?
+Which planet is the hottest in Earth's solar system?
 Venus
 10
 
@@ -614,10 +614,6 @@ What was the first Disney animated film based on the life of a real person?
 Pocahontas
 10
 
-What character did Michael J. Fox play in 'Back to the Future'?
-Marty McFly
-10
-
 What was the predecessor to the United Nations?
 League of Nations
 10
@@ -842,10 +838,6 @@ What grows from an acorn?
 Oak Tree
 10
 
-What prison film starring Tim Robbins was based on a story by Stephen King?
-The Shawshank Redemption
-10
-
 Which U.S. state has "Garden State" as its nickname?
 New Jersey
 10
@@ -966,10 +958,6 @@ Rihanna banned fans from bringing what items to her U.K. concerts in 2008?
 Umbrellas
 10
 
-Who created the alien rock superstar Ziggy Stardust?
-David Bowie
-10
-
 Which young girl helped drive the English from French soil in the 15th century?
 Joan of Arc
 10
@@ -979,7 +967,7 @@ Theodore Roosevelt
 10
 
 What is the biggest supermarket chain in the U.S.?
-Kroger Co.
+Kroger
 10
 
 On every continent there is a city named what?
@@ -1511,7 +1499,7 @@ Sense and Sensibility
 10
 
 Which two countries have the longest shared international border?
-Canada and the U.S.
+Canada and the US
 10
 
 What city hosted the 2014 Winter Olympics?
@@ -1535,7 +1523,7 @@ Three
 10
 
 How many bones do sharks have?
-Zero!
+0
 10
 
 What is the deadliest mammal?
@@ -1612,7 +1600,7 @@ Des Moines
 
 What is the most commonly spoken language in Brazil?
 Portuguese
-10
+5
 
 In what country do more than half of people believe in elves?
 Iceland
@@ -1706,8 +1694,8 @@ Where is Harvard University located?
 Cambridge, Massachusetts
 10
 
-Which marine animals hold hands in their sleep to prevent drifting apart?
-Sea otters, and my system is unable to process that level of cuteness.
+Which marine animal species hold hands in their sleep to prevent drifting apart?
+Sea otter
 10
 
 What famous document begins: "When in the course of human events..."?
@@ -1853,3 +1841,183 @@ Washington Monument
 Where is Mount Rushmore (City, State)?
 Keystone, South Dakota
 5
+
+What country has the highest life expectancy?
+Hong Kong
+10
+
+Where would you be if you were standing on the Spanish Steps?
+Rome
+10
+
+Which language has the more native speakers: English or Spanish?
+Spanish
+10
+
+What is the most common surname in the United States?
+Smith
+10
+
+What disease commonly spread on pirate ships?
+Scurvy
+10
+
+Who was the Ancient Greek God of the Sun?
+Apollo
+10
+
+What was the name of the crime boss who was head of the feared Chicago Outfit?
+Al Capone
+10
+
+What year was the United Nations established?
+1945
+10
+
+Who has won the most total Academy Awards?
+Walt Disney
+10
+
+What artist has the most streams on Spotify?
+Drake
+10
+
+How many minutes are in a full week?
+10080
+10
+
+What car manufacturer had the highest revenue in 2020?
+Volkswagen
+10
+
+How many elements are in the periodic table?
+118
+10
+
+What company was originally called "Cadabra"?
+Amazon
+10
+
+How many faces does a Dodecahedron have?
+12
+10
+
+Queen guitarist Brian May is also an expert in what scientific field?
+Astrophysics
+10
+
+Aureolin is a shade of what color?
+Yellow
+10
+
+How many ghosts chase Pac-Man at the start of each game?
+4
+10
+
+What Renaissance artist is buried in Rome's Pantheon?
+Raphael
+10
+
+What shoe brand makes the "Mexico 66"?
+Onitsuka Tiger
+15
+
+What game studio makes the Red Dead Redemption series?
+Rockstar Games
+10
+
+Who was the last Tsar of Russia?
+Nicholas II
+10
+
+What country drinks the most coffee per capita?
+Finland
+10
+
+What is the 4th letter of the Greek alphabet?
+Delta
+5
+
+What sports car company manufactures the 911?
+Porsche
+2
+
+What city is known as "The Eternal City"?
+Rome
+10
+
+The first person to reach the South Pole was Roald Amundsen.  Where was he from?
+Norway
+10
+
+Who discovered that the earth revolves around the sun (last name)?
+Copernicus
+10
+
+What company was initially known as "Blue Ribbon Sports"?
+Nike
+10
+
+What art form is described as "decorative handwriting or handwritten lettering"?
+Calligraphy
+10
+
+Which planet in Earth's solar system has the most moons?
+Saturn
+10
+
+What country has won the most World Cups?
+Brazil
+10
+
+Kratos is the main character of what video game series?
+God of War
+10
+
+In what country would you find Mount Kilimanjaro?
+Tanzania
+10
+
+A group of pandas is known as a what?
+Embarrassment
+10
+
+What European country experienced the highest rate of population decline from 2015 - 2020?
+Lithuania
+10
+
+How many bones do we have in an ear?
+3
+10
+
+Who famously crossed the Alps with elephants on the way to war with the Romans?
+Hannibal
+10
+
+True or False: Halloween originated as an ancient Irish festival.
+True
+5
+
+What Netflix show had the most streaming views in 2021?
+Squid Game
+10
+
+What software company is headquartered in Redmond, Washington?
+Microsoft
+2
+
+What is the largest Spanish-speaking city in the world?
+Mexico City
+10
+
+What is the world's fastest bird?
+Peregrine Falcon
+10
+
+In what country is the Chernobyl nuclear plant located?
+Ukraine
+10
+
+The Parthenon Marbles are controversially located in what museum?
+British Museum
+10
diff --git a/xtrn/gttrivia/qa/music_movies_and_entertainment.qa b/xtrn/gttrivia/qa/music_movies_and_entertainment.qa
index 5755239d00b198c9934915fbea53bc41cdaade4c..d4662c6ce6a2e9ae3921d34c1cf5cb9b3dc9b5a4 100644
--- a/xtrn/gttrivia/qa/music_movies_and_entertainment.qa
+++ b/xtrn/gttrivia/qa/music_movies_and_entertainment.qa
@@ -510,7 +510,7 @@ What prominent American director won an Oscar for helming Forrest Gump?
 Robert Zemeckis
 10
 
-Three of Jim Carrey's blockbusters�The Mask, Dumb and Dumber and Ace Ventura: Pet Detective�were all released in what year?
+Three of Jim Carrey's blockbusters The Mask, Dumb and Dumber and Ace Ventura: Pet Detective were all released in what year?
 1994
 10
 
@@ -630,7 +630,7 @@ What was the first pandemic era movie to gross over $1 billion at the box office
 Spider-Man: No Way Home
 10
 
-Who is the only actor to appear in Robert Wise�s 1961 West Side Story movie and the 2021 remake?
+Who is the only actor to appear in Robert Wise's 1961 West Side Story movie and the 2021 remake?
 Rita Moreno
 10
 
@@ -642,7 +642,7 @@ What internationally esteemed Malaysian actress has starred in a Bond film, Crou
 Michelle Yeoh
 10
 
-Who won his second Best Actor Oscar in 2021, in the ceremony�s biggest upset?
+Who won his second Best Actor Oscar in 2021, in the ceremony's biggest upset?
 Anthony Hopkins
 10
 
@@ -650,11 +650,11 @@ What indie horror movie boogeyman became an unexpected LGBTQ+ icon of the 21st c
 The Babadook
 10
 
-What kind of bug is on the back of Ryan Gosling�s silk jacket in Drive?
+What kind of bug is on the back of Ryan Gosling's silk jacket in Drive?
 Scorpion
 10
 
-What actress was the queen of 1970s �Blaxploitation� cinema?
+What actress was the queen of 1970s "Blaxploitation" cinema?
 Pam Grier
 10
 
@@ -666,15 +666,15 @@ What is the second (and last) fantasy movie to win Best Picture at the Oscars?
 The Shape of Water
 10
 
-What famous heartthrob is unrecognizable under layers of makeup as The Penguin in 2021�s The Batman?
+What famous heartthrob is unrecognizable under layers of makeup as The Penguin in 2021s The Batman?
 Colin Farrell
 10
 
-In Clueless, what character said, �You�re a virgin who can�t drive?�
+In Clueless, what character said, "You're a virgin who can't drive"?
 Tai
 10
 
-What is the name of the love interest whose �hair looks sexy pushed back� in Mean Girls?
+What is the name of the love interest whose hair looks sexy pushed back in Mean Girls?
 Aaron Samuels
 10
 
@@ -682,7 +682,7 @@ What highly acclaimed Richard Linklater drama was filmed over and produced over
 Boyhood
 10
 
-What is the name of Humperdinck�s kingdom in The Princess Bride?
+What is the name of Humperdinck's kingdom in The Princess Bride?
 Florin
 10
 
@@ -704,7 +704,7 @@ What critically maligned 2004 superhero film co-stars Sharon Stone as an evil co
 Catwoman
 10
 
-Which actress replaced Rachel Weisz as Evelyn O�Connor in The Mummy: Tomb of the Dragon Emperor?
+Which actress replaced Rachel Weisz as Evelyn O'Connor in The Mummy: Tomb of the Dragon Emperor?
 Maria Bello
 10
 
@@ -716,11 +716,11 @@ Who plays Duncan Idaho in Dune (2021)?
 Jason Momoa
 10
 
-Dakota Johnson dropped out of Olivia Wilde�s sophomore feature Don�t Worry Darling to appear in what critically acclaimed 2021 drama?
+Dakota Johnson dropped out of Olivia Wilde's sophomore feature Don't Worry Darling to appear in what critically acclaimed 2021 drama?
 The Lost Daughter
 10
 
-What legendary pop star judges a fashion �walk-off� between Ben Stiller and Owen Wilson in Zoolander?
+What legendary pop star judges a fashion "walk-off" between Ben Stiller and Owen Wilson in Zoolander?
 David Bowie
 10
 
@@ -1182,3 +1182,27 @@ Lady Gaga
 What type of music has been shown to help plants grow better and faster?
 Classical
 10
+
+What character has both Robert Downey Jr. and Benedict Cumberbatch played?
+Sherlock Holmes
+10
+
+What prison film starring Tim Robbins was based on a story by Stephen King?
+The Shawshank Redemption
+10
+
+What is the highest-rated film on IMDb as of January 1st, 2022?
+The Shawshank Redemption
+10
+
+Which grammy-nominated New York rapper died in April of 2021?
+DMX
+10
+
+Who created the alien rock superstar Ziggy Stardust?
+David Bowie
+10
+
+What character did Michael J. Fox play in 'Back to the Future'?
+Marty McFly
+10
diff --git a/xtrn/gttrivia/readme.txt b/xtrn/gttrivia/readme.txt
index ee5b49f53f8d612c0c456ac96640eb52d7e79a79..26451b122f518306540d8cac07cf22ade0c68e77 100644
--- a/xtrn/gttrivia/readme.txt
+++ b/xtrn/gttrivia/readme.txt
@@ -1,11 +1,11 @@
                                Good Time Trivia
-                                 Version 1.01
-                           Release date: 2022-11-25
+                                 Version 1.02
+                           Release date: 2022-12-08
 
                                      by
 
                                 Eric Oulashin
-								 AKA Nightfox
+                                 AKA Nightfox
                           Sysop of Digital Distortion
                   BBS internet address: digitaldistortionbbs.com
                      Alternate address: digdist.bbsindex.com
@@ -57,10 +57,6 @@ scores.  This will delete the scores.json file.
 This is currently a single-player game, but multiple users on different nodes
 can play it simultaneously.
 
-Currently, this trivia game is local to the current BBS only.  In the future,
-I think it would be good to add a feature for networked/inter-BBS games.
-
-
 Answer matching: When a user answers a question, the game can allow non-exact
 answer matching in some circumstances, to account for typos and spelling
 mistakes.  If the answer is a single word up to 12 characters, the game will
@@ -74,6 +70,48 @@ For more information on Levenshtein distances:
 https://www.cuelogic.com/blog/the-levenshtein-algorithm
 
 
+Shared game scores on a server BBS
+----------------------------------
+The game can be configured to share its local game scores, to be stored on a
+remote BBS.  The scores can be shared either by directly contacting the remote
+BBS (via the JSON DB service) and/or by posting the local game scores in one or
+more (networked) message sub-boards (both configurable in gttrivia.ini).  The
+option to post scores in a message sub-board is a backup in case the remote BBS
+is down and cannot be contacted directly.  You may also opt to just have Good
+Time Trivia post scores in a message sub-board and not configure a remote BBS
+server.
+
+Digital Distortion (BBS) is set up to host scores for this game, and the
+default settings in the REMOTE_SERVER section of gttrivia.ini point to
+Digital Distortion, to use the direct-connect JSON DB method to update remote
+scores.
+
+Digital Distortion is also set up to look for scores for this game in the
+Dove-Net Synchronet Data message area, as well as FSXNet Inter-BBS Data.
+
+If your BBS has the Dove-Net message sub-boards, you could configure Good Time
+Trivia to post scores in the Dove-Net Synchronet Data sub-board (using the
+internal code configured on your BBS).  If there are other BBSes besides Digital
+Distortion hosting scores, the host BBS would also need to have Dove-Net and
+have an event configured to periodically run Good Time Trivia to poll Dove-Net
+Synchronet Data and read the game scores.
+
+By default, the game is set up to post scores to Digital Distortion, so you may
+choose to view the scores there or host scores yourself. See section 4
+(Configuration file) for more information on the options to send scores to a
+remote BBS.
+
+When configured to send user scores to a remote BBS and to write scores to a
+message sub-board, that happens whenever a user stops playing a game.  The logic
+for sending the scores is as follows:
+- Try to post the scores to the remote BBS
+- If that fails, then post the scores in the configured message sub-board, if
+  there is one configured.
+That logic should ensure that the scores get posted.  The remote BBS should then
+be configured to have their JSON-DB service running and/or have Good Time Trivia
+periodically scan the same (networked) message sub-board to read the scores.
+
+
 3. Installation & Setup
 =======================
 Aside from readme.txt and revision_history.txt, Good Time Trivia is comprised
@@ -178,6 +216,20 @@ scripts):
 ╚══════════════════════════════════════════════════════════╝
 
 
+That is all you need to do to get Good Time Trivia running.
+
+
+Optional
+--------
+As mentioned in the introduction, server scores can be sent to a remote BBS so
+that scores from players on multiple BBSes can be viewed. Normally, if Good Time
+Trivia is unable to connect to the remote BBS directly, it will fall back to
+posting scores in a networked message sub-board (if configured) as a backup
+option. That happens automatically after a user finishes playing a game, but
+Good Time Trivia can also (optionally) be configured to post game scores in a
+sub-board as a timed event by running gttrivia.js with the
+-post_scores_to_subboard command-line argument.
+
 
 4. Configuration File
 =====================
@@ -200,6 +252,27 @@ numTriesPerQuestion               The maximum number of times a user is
 maxNumPlayerScoresToDisplay       The maximum number of player scores to display
                                   in the list of high scores
 
+scoresMsgSubBoardsForPosting      This can be used to specify a comma-separated
+                                  list of internal sub-board codes for the game
+								  to post user scores in, if you want your user
+								  scores to be shared. In case the remote BBS
+								  in the REMOTE_SERVER setting can't be reached
+								  or there is no remote BBS configured, the game
+								  will post scores in the sub-board(s) specified
+								  here. You can specify more than one sub-board
+								  code in case there are multiple BBSes that
+								  host scores for this game.
+								  Note that this setting is empty by default,
+								  because internal sub-board codes are probably
+								  different on each BBS. Digital Distortion is
+								  set up to host scores for this game, and if
+								  your BBS is connected to Dove-Net, it is
+								  recommended to use your BBS's internal code
+								  code for the Dove-Net Synchronet Data
+								  sub-board here. FSXNet also has an InterBBS
+								  Data area that might be used for conveying
+								  game scores to a host BBS.
+
 [COLORS] section
 ----------------
 In this section, the color codes are simply specified by a string of color
@@ -270,6 +343,19 @@ deleteScoresOlderThanDays         The number of days to keep old player scores.
                                   The background service will remove player
 								  scores older than this number of days.
 
+scoresMsgSubBoardsForReading      This can be used to specify a comma-separated
+                                  list of internal sub-board codes for the game
+								  to read user scores from, for client BBSes
+								  that post their game scores there. See section
+								  5 (Optional: Configuring your BBS to host
+								  player scores) for information on adding an
+								  event in SCFG to periodically read scores
+								  from the sub-board(s) if you want to host game
+								  scores on your BBS. By default, the game is
+								  set up to post scores to Digital Distortion,
+								  so you may choose to view the scores there or
+								  host scores yourself.
+
 
 5. Optional: Configuring your BBS to host player scores
 =======================================================
@@ -297,3 +383,51 @@ dir=../xtrn/gttrivia/server/
 
 It would then probably be a good idea to stop and re-start your Synchronet BBS
 in order for it to recognize that you have a new JSON database configured.
+
+
+Periodic reading of scores from a message sub-board
+---------------------------------------------------
+BBSes with the game installed could configure their game to post scores in a
+(networked) message sub-board.  If you decide to host game scores on your BBS,
+it's also a good idea to configure your BBS to read scores from a networked
+message sub-board (which would need to be the same one that BBSes post in). For
+instance, you could set it up to read scores from Dove-Net Synchronet Data,
+FSXNet InterBBS Data, or perhaps another networked sub-board that is meant to
+carry BBS data.
+
+To specify which sub-board(s) to read scores from, you can specify those as a
+comma-separated list of internal sub-board codes using the
+scoresMsgSubBoardsForReading setting under the [SERVER] section of
+gttrivia.ini.
+
+Then, in SCFG, you will need to configure an event to run periodically to run
+gttrivia.js to read those message sub-boards for game scores. You can do that
+in SCFG > External Programs > Timed Events. Set it up to run gttrivia.js with
+the command-line parameter -read_scores_from_subboard
+Add an event as follows (internal code can be what you want; GTRIVSIM is short
+for Good Time Trivia scores import):
+
+╔═══════════════════════════════════════════════════════════════[< >]╗
+║                        GTRIVSIM Timed Event                        ║
+╠════════════════════════════════════════════════════════════════════╣
+║ │Internal Code                   GTRIVSIM                          ║
+║ │Start-up Directory              ../xtrn/gttrivia                  ║
+║ │Command Line                    ?gttrivia.js -read_scores_from_subboard
+║ │Enabled                         Yes                               ║
+║ │Execution Node                  12                                ║
+║ │Execution Months                Any                               ║
+║ │Execution Days of Month         Any                               ║
+║ │Execution Days of Week          All                               ║
+║ │Execution Frequency             96 times a day                    ║
+║ │Requires Exclusive Execution    No                                ║
+║ │Force Users Off-line For Event  No                                ║
+║ │Native Executable/Script        Yes                               ║
+║ │Use Shell or New Context        No                                ║
+║ │Background Execution            No                                ║
+║ │Always Run After Init/Re-init   No                                ║
+║ │Error Log Level                 Error                             ║
+╚════════════════════════════════════════════════════════════════════╝
+
+The number of times per day is up to you, but it would probably be beneficial
+for this to happen frequently so that scores are kept up to date. In the above
+example, 96 times per day would mean it would run every 15 minutes.
\ No newline at end of file