/* ChessMaster3000.thor by Troels Walsted Hansen
** $VER: ChessMaster3000.thor 1.21 (27.11.98)
**
** 1.21: Fixed for use on TCP/IP systems by Maurizio Lotauro
**
** An ARexx script for playing a game of chess against another THOR-
** user through messages on a BBS. Please refer to the included file
** ChessMaster3000.doc for detailed information.
*/

options results

/* needs THOR and bbsread.library functions */

p = ' ' || address() || ' ' || show('P',,)
thorport = pos(' THOR.',p)

if thorport > 0 then thorport = word(substr(p,thorport+1),1)
else
do
	say 'No THOR port found!'
	exit 10
end

if ~show('p', 'BBSREAD') then
do
	address command
		"run >nil: `GetEnv THOR/THORPath`bin/LoadBBSRead"
		"WaitForPort BBSREAD"
end

/* save out msgtext and determine whether to continue an old or start a new game */

address(thorport)
THORTOFRONT
SAVEMESSAGE CURRENT FILENAME '"T:ChessMaster3000.thor.temp"' NOHEADER NOANSI

if ~open(ifh, 'T:ChessMaster3000.thor.temp', R) then
do
	REQUESTNOTIFY TEXT '"Cannot open temporary file: T:ChessMaster3000.thor.temp"' BT '"_Ok"'
	exit
end

/*
***ChessMaster3000, round #1
*/

newgame = 0
firstmove = 1

do until(pos('***ChessMaster3000', line) > 0)
	if eof(ifh) then
	do
		REQUESTNOTIFY TEXT '"Message contains no ChessMaster3000 data!"' BT '"_Ok"'
		REQUESTNOTIFY TEXT '"Start new game?"' BT '"_Yes|_No"'
		if(rc = 0 & result = 1) then
		do
			call close(ifh)

			/* initiate variables */
			call NewGame()

			firstmove = 1

			/* write all the data */
			call WriteData()

			address(thorport)
			SHOWTEXT 'T:ChessMaster3000.thor.temp'

			/* move first turn */
			call PlayMove()

			firstmove = 0

			/* write all the data */
			call WriteData()

			address(thorport)
			SHOWTEXT 'T:ChessMaster3000.thor.temp'

			/* post the file */
			call PostMsg()
			signal exit
		end
		signal exit
	end
	line = readln(ifh)
end

firstmove = 0

/* read the rest of the chess info */

call ReadData()

/* move the pieces etc. */

call PlayMove()

/* write all the data to a file */

call WriteData()

address(thorport)
SHOWTEXT 'T:ChessMaster3000.thor.temp'

/* initiate all variables from message info */

address(thorport)
CURRENTMSG stem MSG

address(bbsread)
READBRMESSAGE bbsname '"'MSG.BBSNAME'"' confname '"'MSG.CONFNAME'"' msgnr '"'MSG.MSGNR'"' headstem HEAD textstem TEXT

EVENT.TYPE			= 1					/* replymsg */
EVENT.TONAME		= HEAD.FROMNAME
EVENT.SUBJECT		= HEAD.SUBJECT
EVENT.CONFERENCE	= MSG.CONFNAME
EVENT.REFNR			= MSG.MSGNR
EVENT.REFORGINALNR = HEAD.ORGINALNR
EVENT.TOADDR      = HEAD.FROMADDR

/* Not needed?
EVENT.REFID 		= HEAD.REFID
EVENT.TOADDR 		= TEXT.REPLYADDR
*/

/* post the file as a reply to the current message */

call PostMsg()
signal exit

NewGame:
	/* initiate all variables otherwise read from the message text */

	roundnumber = 0
	newgame = 1

	pos.1.8 = ' #C# '; pos.2.8 = ' #N# '; pos.3.8 = ' #B# '; pos.4.8 = ' #Q# '; pos.5.8 = ' #K# '; pos.6.8 = ' #B# '; pos.7.8 = ' #N# '; pos.8.8 = ' #C# '
	pos.1.7 = ' #P# '; pos.2.7 = ' #P# '; pos.3.7 = ' #P# '; pos.4.7 = ' #P# '; pos.5.7 = ' #P# '; pos.6.7 = ' #P# '; pos.7.7 = ' #P# '; pos.8.7 = ' #P# '

	do y=6 to 3 by -1
		do x=1 to 8
			pos.x.y = '   '
		end
	end

	pos.1.2 = ' P '; pos.2.2 = ' P '; pos.3.2 = ' P '; pos.4.2 = ' P '; pos.5.2 = ' P '; pos.6.2 = ' P '; pos.7.2 = ' P '; pos.8.2 = ' P '
	pos.1.1 = ' C '; pos.2.1 = ' N '; pos.3.1 = ' B '; pos.4.1 = ' Q '; pos.5.1 = ' K '; pos.6.1 = ' B '; pos.7.1 = ' N '; pos.8.1 = ' C '

	blacklosses = ''
	whitelosses = ''

	/* initiate all variables otherwise read from the message header data */

	EVENT.TYPE = 0 /* entermsg */

	address(bbsread)
	GETBBSLIST stem BBSLIST
	if(rc ~= 0) then
	do
		address(thorport)
		REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"'
		signal exit
	end

	address(thorport)
	REQUESTLIST instem BBSLIST title '"Select BBS:"' SIZEGADGET
	if(rc ~= 0) then signal exit
	else MSG.BBSNAME = result

	address(bbsread)
	GETCONFLIST '"'MSG.BBSNAME'"' CONFLIST
	if(rc ~= 0) then
	do
		address(thorport)
		REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"'
		signal exit
	end

	address(thorport)
	REQUESTLIST instem CONFLIST title '"Select conf:"' SIZEGADGET
	if(rc ~= 0) then signal exit
	else EVENT.CONFERENCE = result

	REQUESTSTRING TITLE '"Please enter subject of message:"' BT '"_Ok|_Cancel"' ID '"ChessMaster3000"' MAXCHARS 100
	EVENT.SUBJECT = result
	if(rc ~= 0 | EVENT.SUBJECT = "") then signal exit

	do forever
		REQUESTSTRING TITLE '"Please enter the name of your opponent:"' BT '"_Ok|_Cancel "' MAXCHARS 200
		if(rc ~= 0) then signal exit
		EVENT.TONAME = result

		if(upper(EVENT.TONAME) ~= "ALL") then
		do
			address(bbsread)
			SEARCHBRUSER bbsname '"'MSG.BBSNAME'"' stem USERS search '"'EVENT.TONAME'"' name address alias suggestusersstem SUG
			if(rc ~= 0) then signal exit

			if(result > 0) then
			do
				drop LIST.
				drop USERTAGS.

				LIST.COUNT = USERS.COUNT

				do n = 1 to USERS.COUNT
					LIST.n.USERNR = USERS.n.USERNR

					address(bbsread)
					READBRUSER bbsname '"'MSG.BBSNAME'"' usernr USERS.n.USERNR tagsstem USERTAGS
					if(rc ~= 0) then signal exit
					LIST.n = USERTAGS.NAME

					if(symbol("USERTAGS.ADDRESS") = "VAR") then
						LIST.n.ADDRESS = USERTAGS.ADDRESS
				end

				address(thorport)
				REQUESTLIST instem LIST title '"Select user:"'
				if(rc ~= 0) then
				do
					if(rc ~= 5) then REQUESTNOTIFY TEXT '"'THOR.LASTERROR'"' BT '"_Ok"'
					signal exit
				end

				EVENT.TONAME = result

				do n = 1 to LIST.COUNT
					if(LIST.n = EVENT.TONAME) then
						EVENT.TOADDR = LIST.n.ADDRESS
				end
				leave
			end
			else
			do
				if(symbol("SUG.COUNT") = "VAR") then do
					address(thorport)
					REQUESTLIST instem SUG title '"Select user:"'
					if(rc ~= 0) then
					do
						if(rc ~= 5) then REQUESTNOTIFY TEXT '"'THOR.LASTERROR'"' BT '"_Ok"'
						signal exit
					end

					EVENT.TONAME = result

					do n = 1 to SUG.COUNT
						if(SUG.n = EVENT.TONAME) then
							usernumber = SUG.n.USERNR
					end

					drop USERTAGS.

					address(bbsread)
					READBRUSER bbsname '"'MSG.BBSNAME'"' usernr usernumber tagsstem USERTAGS
					if(rc ~= 0) then signal exit

					if(symbol("USERTAGS.ADDRESS") = "VAR") then
						EVENT.TOADDR = USERTAGS.ADDRESS

					leave
				end
				else
				do
					address(thorport)
					REQUESTNOTIFY TEXT '"No matching users found, try again?"' BT '"_Ok|_Cancel"'
					if(rc ~= 0) then signal exit
					if(result = 0) then signal exit
				end
			end
		end
		else signal exit /* doesn't work with ALL */
	end

	blackplayer = EVENT.TONAME
RETURN

ReadData:
	roundnumber = substr(line, lastpos('#', line)+1)

	/*

	Black: Matthias Bartosik
	White: Troels Walsted_Hansen
	*/

	call readln(ifh)
	blackplayer = substr(readln(ifh), 8)
	whiteplayer = substr(readln(ifh), 8)

	/*

	Status: White Pawn at H1 exchanged for Bishop

	     +---+---+---+---+---+---+---+---+
	*/

	do 4; call readln(ifh); end

	/*
	   8 | #C# | #N# | #B# | #Q# | #K# | #B# | #N# | #C# |
	     +---+-^-+---+-^-+---+-^-+---+-^-+
	   7 | #P# | #P# | #P# | #P# | #P# | #P# | #P# | #P# |
	     +-^-+---+-^-+---+-^-+---+-^-+---+
	   6 |   |   |   |   |   |   |   |   |
	     +---+-^-+---+-^-+---+-^-+---+-^-+
	   5 |   |   |   |   |   |   |   |   |
	     +-^-+---+-^-+---+-^-+---+-^-+---+
	   4 |   |   |   |   |   |   |   |   |
	     +---+-^-+---+-^-+---+-^-+---+-^-+
	   3 |   |   |   |   |   |   |   |   |
	     +-^-+---+-^-+---+-^-+---+-^-+---+
	   2 | P | P | P | P | P | P | P | P |
	     +---+-^-+---+-^-+---+-^-+---+-^-+
	   1 | C | N | B | Q | K | B | N | C |
	     +-^-+---+-^-+---+-^-+---+-^-+---+
	       a   b   c   d   e   f   g   h

	Black losses:
	*/

	line.8 = readln(ifh);		call readln(ifh)
	line.7 = readln(ifh);		call readln(ifh)
	line.6 = readln(ifh);		call readln(ifh)
	line.5 = readln(ifh);		call readln(ifh)
	line.4 = readln(ifh);		call readln(ifh)
	line.3 = readln(ifh);		call readln(ifh)
	line.2 = readln(ifh);		call readln(ifh)
	line.1 = readln(ifh)

	do 4; call readln(ifh); end

	/*
	#C#, #Q#

	White losses:
	B, P, Q
	*/

	blacklosses = readln(ifh)
	do 2; call readln(ifh); end
	whitelosses = readln(ifh)

	call close(ifh)

	/* parse the input */

	do y=1 to 8
		line.y = delstr(line.y, 1, 6)

		do x=1 to 8
			pos.x.y = substr(line.y, 1, pos('|', line.y)-1)
			line.y = delstr(line.y, 1, pos('|', line.y))
		end
	end
RETURN

PlayMove:
	/* determine who the current player is */

	address(thorport)
	CURRENTBBS stem CURRENT
	if(rc ~= 0) then
	do
		address(thorport)
		REQUESTNOTIFY TEXT '"'THOR.LASTERROR'"' BT '"_Ok"'
		signal exit
	end

	address(bbsread)
	GETBBSDATA bbsname '"'CURRENT.BBSNAME'"' stem BBSDATA
	if(rc ~= 0) then
	do
		address(thorport)
		REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"'
		signal exit
	end

	if(BBSDATA.USERNAME = '') then
	do
		GETGLOBALDATA stem GLOBALDATA
	        if(rc ~= 0) then
	        do
	        	address(thorport)
	        	REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"'
	        	signal exit
	        end

		if(GLOBALDATA.USERNAME = '') then signal exit
		else username = GLOBALDATA.USERNAME
	end
	else username = BBSDATA.USERNAME

	if(newgame) then whiteplayer = username

	select
		when(username = blackplayer) then
		do
			color = 'Black'
			othercolor = 'White'
		end

		when(username = whiteplayer) then
		do
			color = 'White'
			othercolor = 'Black'
		end

		otherwise signal exit
	end

	/* ask user to specify move */

	exchangepawn = 0
	longcastle = 0
	shortcastle = 0
	passant = 0

	address(thorport)
	REQUESTSTRING TITLE '"ChessMaster3000"' BODY '"' || color || ' player enter your move\non the form ''xyxy''.' || '"' BT '"_Ok|_Special move|_Cancel"' MAXCHARS 4
	if(rc ~= 0) then signal exit

	/* normal move */

	if(result ~= '') then
	do
		origmovestr = upper(result)

		movestr = translate(origmovestr, '12345678', 'ABCDEFGH')

		fromxpos = substr(movestr, 1, 1);	fromypos = substr(movestr, 2, 1)
		toxpos = substr(movestr, 3, 1);		toypos = substr(movestr, 4, 1)

		/* verify the integrity of the coordinates */

		select
			when(fromxpos > 8 | fromxpos < 1) then errormsg = 'FROM x-coordinate out of range.'
			when(fromypos > 8 | fromypos < 1) then errormsg = 'FROM y-coordinate out of range.'
			when(toxpos > 8 | toxpos < 1) then errormsg = 'TO x-coordinate out of range.'
			when(toypos > 8 | toypos < 1) then errormsg = 'TO y-coordinate out of range.'
			when(pos.fromxpos.fromypos = '   ') then errormsg = 'Invalid FROM coordinates, no chess piece found.'
			when(left(strip(pos.fromxpos.fromypos, B), 1) = '#' & color = 'White' | left(strip(pos.fromxpos.fromypos, B), 1) ~= '#' & color = 'Black') then errormsg = 'Invalid FROM coordinates, trying to\nmove other player''s chess piece.'
			when(pos.toxpos.toypos ~= '   ' & left(strip(pos.toxpos.toypos, B), 1) ~= '#' & color = 'White' | left(strip(pos.toxpos.toypos, B), 1) = '#' & color = 'Black') then errormsg = 'TO square is occupied by your own piece.'
			otherwise errormsg = ''
		end

		if(errormsg ~= '') then
		do
			address(thorport)
			REQUESTNOTIFY TEXT '"'errormsg'"' BT '"_Ok"'
			signal exit
		end

		/* determine whether an enemy piece has been beaten */

		frompiece = compress(pos.fromxpos.fromypos, '# ')
		topiece = compress(pos.toxpos.toypos, '# ')

		if(pos.toxpos.toypos ~= '   ') then
		do
			if(topiece = 'K') then
			do
				address(thorport)
				do 50; BEEP; end
				REQUESTNOTIFY TEXT '"You have won the game!"' BT '"H_ooya!"'
				/* gotta post a fancy message here */
				signal exit
			end

			if(color = 'Black') then whitelosses = whitelosses || ', ' || strip(pos.toxpos.toypos, B)
			else blacklosses = blacklosses || ', ' || strip(pos.toxpos.toypos, B)

			select
				when(left(blacklosses, 1) = ',') then blacklosses = substr(blacklosses, 3)
				when(left(whitelosses, 1) = ',') then whitelosses = substr(whitelosses, 3)
				otherwise nop
			end
		end
		else anyonebeaten = 'FALSE'

		/* move the piece to the TO square and clear the FROM square */

		pos.toxpos.toypos = pos.fromxpos.fromypos
		pos.fromxpos.fromypos = '   '
	end
	else	/* special move */
	do
		address(thorport)
		REQUESTNOTIFY TEXT '"Select special move:"' BT '"_Exchange Pawn|C_astle|_Passant|_Cancel"'
		if(rc ~= 0) then signal exit

		select
			when(result = 0) then signal exit	/* Cancel 			*/
			when(result = 1) then				/* Exchange Pawn 	*/
			do
				exchangepawn = 1

				if(color = 'Black') then y = 1
				else y = 8

				availpawn.count = 0

				do x=1 to 8
					if(compress(pos.x.y, '# ') = 'P') then
					do
						availpawn.count = availpawn.count+1
						k = availpawn.count
						availpawn.k = translate(x, 'ABCDEFGH', '12345678') || y
					end
				end

				if(availpawn.count = 0) then
				do
					address(thorport)
					REQUESTNOTIFY TEXT '"No Pawn-exchanging is possible."' BT '"_Ok"'
					signal exit
				end

				if(availpawn.count ~= 1) then
				do
					/* change to REQUESTNOTIFY !? */
					address(thorport)
					REQUESTLIST TITLE '"Choose one set of coordinates"' instem availpawn SIZEGADGET
					if(rc ~= 0) then signal exit

					pawncoord = result
				end
				else pawncoord = availpawn.1

				address(thorport)
				REQUESTNOTIFY TEXT '"Select new chess piece:"' BT '"_Queen|_Bishop|K_night|_Castle"'
				if(rc ~= 0) then signal exit

				select
					when(result = 0) then signal exit
					when(result = 1) then frompiece = 'Q'
					when(result = 2) then frompiece = 'B'
					when(result = 3) then frompiece = 'N'
					when(result = 4) then frompiece = 'C'
					otherwise frompiece = 'P'
				end

				if(color = 'Black') then styledfrompiece = ' #' || frompiece || '# '
				else styledfrompiece = ' ' || frompiece || ' '

				x = translate(left(pawncoord, 1), '12345678', 'ABCDEFGH')
				y = right(pawncoord, 1)

				pos.x.y = styledfrompiece
			end

			when(result = 2) then		/* Castle			*/
			do
				if(color = 'Black') then y = 8
				else y = 1

				if(compress(pos.1.y, '# ') = 'C' & pos.2.y = '   ' & pos.3.y = '   ' & pos.4.y = '   ' & compress(pos.5.y, '# ') = 'K') then longcastle = 1
				if(compress(pos.5.y, '# ') = 'K' & pos.6.y = '   ' & pos.7.y = '   ' & compress(pos.8.y, '# ') = 'C') then shortcastle = 1

				if(longcastle = 0 & shortcastle = 0) then
				do
					address(thorport)
					REQUESTNOTIFY TEXT '"You cannot perform a castling."' BT '"_Ok"'
					signal exit
				end

				gadstr = ''

				if(longcastle = 1 & shortcastle = 1) then
				do
					address(thorport)
					REQUESTNOTIFY TEXT '"Select which kind of castling:"' BT '"_Long|_Short|_Cancel"'
					if(rc ~= 0) then signal exit

					if(result = 1) then shortcastle = 0
					else longcastle = 0
				end

				/* style 'em */

				if(color = 'Black') then
				do
					styledking = ' #K# '
					styledcastle = ' #C# '
				end
				else
				do
					styledking = ' K '
					styledcastle = ' C '
				end

				select
					when(longcastle = 1) then
					do
						pos.1.y = '   ';		pos.5.y = '   '
						pos.3.y = styledking;	pos.4.y = styledcastle
					end

					when(shortcastle = 1) then
					do
						pos.8.y = '   ';		pos.5.y = '   '
						pos.7.y = styledking;	pos.6.y = styledcastle
					end

					otherwise signal exit
				end
			end

			when(result = 3) then		/* Passant			*/
			do
				passant = 1

				/* beating 'en passant' may happen only if two opponent pawns are
				   standing next to each other on either y=5 | y=4. */

				if(color  = 'Black') then y = 4
				else y = 5

				availpassant.count = 0

				do x=1 to 8
					k = x+1
					if(pos.x.y = ' P ' & pos.k.y = ' #P# ' | pos.x.y = ' #P# ' & pos.k.y = ' P ') then
					do
						/* determine which one belongs to the current player */
						select
							when(pos.x.y = ' P ' & color = 'White') then
							do
								passantkillercolor = 'White'
								passantvictimcolor = 'Black'
								passantkillerx = x
								passantvictimx = k
							end

							when(pos.k.y = ' P ' & color = 'White') then
							do
								passantkillercolor = 'White'
								passantvictimcolor = 'Black'
								passantkillerx = k
								passantvictimx = x
							end

							when(pos.x.y = ' #P# ' & color = 'Black') then
							do
								passantkillercolor = 'Black'
								passantvictimcolor = 'White'
								passantkillerx = x
								passantvictimx = k
							end

							when(pos.k.y = ' #P# ' & color = 'Black') then
							do
								passantkillercolor = 'Black'
								passantvictimcolor = 'White'
								passantkillerx = k
								passantvictimx = x
							end

							otherwise signal exit
						end

						/* determine whether the appropriate squares are open */

						if(passantkillercolor = 'Black' & pos.passantvictimx.2 = '   ' & pos.passantvictimx.3 = '   ' | passantkillercolor = 'White' & pos.passantvictimx.6 = '   ' & pos.passantvictimx.7 = '   ') then
						do
							availpassant.count = availpassant.count+1
							j = availpassant.count
							availpassant.j = translate(passantkillerx, 'ABCDEFGH', '12345678') || y || ' beating ' || translate(passantvictimx, 'ABCDEFGH', '12345678') || y
						end
					end
				end

				if(availpassant.count = 0) then
				do
					address(thorport)
					REQUESTNOTIFY TEXT '"No passant opportunities available."' BT '"_Ok"'
					signal exit
				end

				if(availpassant.count ~= 1) then
				do
					address(thorport)
					REQUESTLIST TITLE '"Choose one scenario:"' instem availpassant SIZEGADGET
					if(rc ~= 0) then signal exit

					passantcoord = result
				end
				else passantcoord = availpassant.1

				toxpos = translate(substr(passantcoord, 12, 1), '12345678', 'ABCDEFGH')

				if(color = 'Black') then whitelosses = whitelosses || ', ' || strip(pos.toxpos.y, B)
				else blacklosses = blacklosses || ', ' || strip(pos.toxpos.y, B)

				select
					when(left(blacklosses, 1) = ',') then blacklosses = substr(blacklosses, 3)
					when(left(whitelosses, 1) = ',') then whitelosses = substr(whitelosses, 3)
					otherwise nop
				end

				/* clear the TO square */

				pos.toxpos.y = '   '
				passantcoord = right(passantcoord, 2)
			end

			otherwise signal exit		/* just in case		*/
		end
	end

	roundnumber = roundnumber+1
RETURN

WriteData:
	/* write the whole thing to a temp file */

	call open(ofh, 'T:ChessMaster3000.thor.temp', W)

	call writeln(ofh, '***ChessMaster3000, round #' || roundnumber)
	call writeln(ofh, '')
	call writeln(ofh, 'Black: ' || blackplayer)

	if(firstmove) then whiteplayer = 'You.'

	call writeln(ofh, 'White: ' || whiteplayer)
	call writeln(ofh, '')

	select
		when(topiece = 'K') then str = ' King'
		when(topiece = 'Q') then str = ' Queen'
		when(topiece = 'C') then str = ' Castle'
		when(topiece = 'N') then str = ' Knight'
		when(topiece = 'B') then str = ' Bishop'
		when(topiece = 'P') then str = ' Pawn'
		otherwise str = ' Unknown'
	end

	if(anyonebeaten ~= 'FALSE') then beatenstr = ' beating ' || othercolor || str
	else beatenstr = ''

	select
		when(frompiece = 'K') then str = ' King '
		when(frompiece = 'Q') then str = ' Queen '
		when(frompiece = 'C') then str = ' Castle '
		when(frompiece = 'N') then str = ' Knight '
		when(frompiece = 'B') then str = ' Bishop '
		when(frompiece = 'P') then str = ' Pawn '
		otherwise str = ' Unknown '
	end

	select
		when(firstmove)		then 	statstr = 'Status: Waiting for your first move.'
		when(exchangepawn)	then	statstr = 'Status: ' || color || ' Pawn at ' || pawncoord || ' exchanged for' || str
		when(longcastle)	then	statstr = 'Status: ' || color || ' performed a long castling'
		when(shortcastle)	then	statstr = 'Status: ' || color || ' performed a short castling'
		when(passant)		then 	statstr = 'Status: ' || color || ' Pawn beat a ' || othercolor || ' Pawn en passant at ' || passantcoord
		otherwise					statstr = 'Status: ' || color || str || 'from ' || left(origmovestr, 2) || ' to ' || right(origmovestr, 2) || beatenstr
	end

	call writeln(ofh, statstr)
	call writeln(ofh, '')
	call writeln(ofh, '     +---+---+---+---+---+---+---+---+')

	do y=8 to 1 by -1
		call writeln(ofh, '   ' || y || ' |' || pos.1.y || '|' || pos.2.y || '|' || pos.3.y || '|' || pos.4.y || '|' || pos.5.y || '|' || pos.6.y || '|' || pos.7.y || '|' || pos.8.y || '|')
		if(y//2 = 0) then str = '     +---+-^-+---+-^-+---+-^-+---+-^-+'
		else str = '     +-^-+---+-^-+---+-^-+---+-^-+---+'
		call writeln(ofh, str)
	end

	call writeln(ofh, '       a   b   c   d   e   f   g   h')
	call writeln(ofh, '')
	call writeln(ofh, 'Black losses:')
	call writeln(ofh, blacklosses)
	call writeln(ofh, '')
	call writeln(ofh, 'White losses:')
	call writeln(ofh, whitelosses)
	call writeln(ofh, '')
	call writeln(ofh, 'K = King      B = Bishop     C = Castle')
	call writeln(ofh, 'Q = Queen     N = Knight     P = Pawn')

	call close(ofh)
RETURN

PostMsg:
	address(bbsread)
	UNIQUEMSGFILE bbsname '"'MSG.BBSNAME'"' stem UNIQUEFILE
	if(rc ~= 0) then
	do
		address(thorport)
		REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"'
		signal exit
	end

	address command 'copy >nil: T:ChessMaster3000.thor.temp TO ' || UNIQUEFILE.NAME
	EVENT.MSGFILE = UNIQUEFILE.FILEPART

	address(bbsread)
	WRITEBREVENT bbsname '"'MSG.BBSNAME'"' event EVENT.TYPE stem EVENT
	if(rc ~= 0) then
	do
		address(thorport)
		REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"'
		signal exit
	end

	address(thorport)
	REQUESTNOTIFY TEXT '"Edit message?"' BT '"_Yes|_No"'
	if(result = 1) then STARTEDITOR FILE '"'UNIQUEFILE.NAME'"'
RETURN

signal exit:
	address command 'delete T:ChessMaster3000.thor.temp quiet'
	exit
