ZX Spectrum Multi User Dungeon (MUD)

Propose new game/software design concepts or new game/software ideas. They can be as whimsical as you like, just be careful you don't ask someone to make it for you...
Post Reply
User avatar
MonkZy
Microbot
Posts: 189
Joined: Thu Feb 08, 2018 1:01 pm

ZX Spectrum Multi User Dungeon (MUD)

Post by MonkZy »

Many years ago, I was fortunate to be at a school with multiple networked BBC Masters. The machines were networked using Econet, there was also a file server connected to a Winchester HDD (30MB if my memory serves me well). This allowed us to play a game called 'The Cave'. The game was a multi user dungeon, a text adventure with multiple users. Some hours were spent mucking about roaming the cave, bashing teachers/1st years/noobs. Much fun was had. This was in fact my very first experience of online gaming.

Fast forward to around 1998 when I finally had a modem and access to the internet. By this time MUD's had come a long way. Class based adventuring with huge worlds to explore and puzzles to solve. Shops, traders and currency were all now part of adventure systems. Many hours were lost leveling characters and diving deep into player generated lore.

MUD's are very different to usual text adventures. Politics and social structures play a huge part in the game, which can bring extra enjoyment to text adventuring but can also bring drama and upset. So MUD's may not be for all text adventure fans, some preferring the solo questing found on traditional text adventures.

I am tinkering with the idea of making a ZX Spectrum MUD client. MUD's are a server/client system. All of the game data and processing is done server side. The client is a simple Telnet client, a dumb terminal. On the PC many customised telnet clients have been made that give you many MUD related functions. I intend to code a telnet client that is totally geared toward MUD's.

My progress so far is purely server side. I have managed to compile a build of CircleMUD (based on DikuMUD) and have had it up and running, tested with a Linux telnet client. CircleMUD has some great resources for editing the files that create the world. It is a full feature server that has shops, mobile non-player characters, objects, combat and much more. It also has a way of editing the world from inside the game, which allows people to easily collaborate with the building of the world. So, I think I have the server side sorted, although I have plenty to learn about the admin. I have compiled the code on a RaspberryPi 2 I had spare. I can keep the server on 24/7 at little cost to me. I am a little worried about the security risk as I will have to give out my home IP and forward a port to the Pi, so maybe I could get some advice on this. I may need a VPN or some such. For now I would be fine to give my IP in DM to interested parties. Currently the server is loaded with the default world, which works just fine. I intend to alter this soon, the start location will be the Baron of Beef pub, maybe have a Sir Clive and Chris Curry mobile.

The client side will be written for Spectranet. I do not have hardware sadly, my two real speccies are not in good working order so I think spending out for a Spectranet card would be unwise at this time (this may change soon). FUSE does have excellent Spectranet support though, and I can develop with this. If interest is there I would like to make a SpecNEXT version and also a version for Russian clones and other Spectrum networking interfaces. I would need help for those.

I am posting this to create a thread to gauge interest and to ramble about the client code.

Links for more info:

CircleMUD documentation : https://www.circlemud.org/cdp/
MUD Wikipedia page : https://en.wikipedia.org/wiki/MUD

MUD's can be also used as a chatroom, similar to IRC. More fun than IRC because the emotes are more complex and object based, and you can bash each other with a wide array of blunt and sharpened instruments.

Please reply if this idea interests you, or if you have any ideas of the direction of the project.
3 x

p13z
Berk
Posts: 11
Joined: Sun Feb 17, 2019 10:41 pm

Re: ZX Spectrum Multi User Dungeon (MUD)

Post by p13z »

Sounds like a perfect use for Spectranet. My Speccy and Spectranet have been packed away in the loft for a few years - but I would be keen to try this out if it, and my Speccy, see the light of day.
0 x

User avatar
MonkZy
Microbot
Posts: 189
Joined: Thu Feb 08, 2018 1:01 pm

Re: ZX Spectrum Multi User Dungeon (MUD)

Post by MonkZy »

@p13z Thanks for the feed back. It will take me some time to code the client, but once I get something useful to test it would be great if you can help with a proper hardware test.
1 x

User avatar
MonkZy
Microbot
Posts: 189
Joined: Thu Feb 08, 2018 1:01 pm

Re: ZX Spectrum Multi User Dungeon (MUD)

Post by MonkZy »

Update:

Baby steps have been taken with the coding of the client. I have successfully got the Spectrum communicating with the server. At this point the client only receives the greeting message from the MUD after sending a handshake. Not much, but I am am pretty chuffed.

Image

I have decided to use the 42 column print routine that is built into the Spectranet ROM. I was going to use a proportional spaced text, but a fixed column print mode is better for formatting text and for ASCII art. CircleMUD is geared for an 80 column terminal so I will have to make code which neatly wraps the text into a 42 column client. Some texts will have to be altered in the MUD to accommodate the 42 columns.

To Do's:

Code a scroll routine to scroll the output text.
Code the keyboard input and send text routine.
Code a socket polling routine that checks the socket for incoming text.

Decisions to be made:

How will I handle the text? Do I store a buffer of text that can be rolled back, it would be useful to be able to do this as text comes at you fast in a busy MUD? Do I simply have a 'more..' message when the incoming text goes over the 28 lines of the client screen, wait for the user to hit a key to continue and discard the text which leaves the screen?

At this point I would really like to say a huge thanks to Winston (Dylan Smith), @Guesser and all the other people involved in making the Spectranet and the excellent documentation. Also a big thanks to the authors/maintainers of the FUSE project.

Code:
SpoilerShow

labels.asm contains declarations of all the entry points and constants used by the Spectranet. It is an abridged version of spectranet.inc.

Code: Select all

;;; Defined Labels

; Hardware page-in entry points
PAGEIN		equ 0x3FF9
PAGEOUT		equ 0x007C
HLCALL		equ 0x3FFA
IXCALL		equ 0x3FFD

; Jump table entry points
SOCKET		equ 0x3E00	; Allocate a socket
CLOSE		equ 0x3E03	; Close a socket
LISTEN		equ 0x3E06	; Listen for incoming connections
ACCEPT		equ 0x3E09	; Accept an incoming connection
BIND		equ 0x3E0C	; Bind a local address to a socket
CONNECT		equ 0x3E0F	; Connect to a remote host
SEND		equ 0x3E12	; Send data 
RECV		equ 0x3E15	; Receive data 

POLL		equ 0x3E1E	; Poll a list of sockets
POLLALL		equ 0x3E21	; Poll all open sockets
POLLFD		equ 0x3E24	; Poll a single socket
GETHOSTBYNAME	equ 0x3E27	; Look up a hostname
PUTCHAR42	equ 0x3E2A	; 42 column print write a character
PRINT42		equ 0x3E2D	; 42 column print a null terminated string
CLEAR42		equ 0x3E30	; Clear the screen and reset 42-col print

LONG2IPSTRING	equ 0x3E39	; Convert a 4 byte big endian long to an IP
IPSTRING2LONG	equ 0x3E3C	; Convert an IP to a 4 byte big endian long
ITOA8		equ 0x3E3F	; Convert a byte to ascii
RAND16		equ 0x3E42	; 16 bit PRNG

GETKEY		equ 0x3E66	; Get a key from the keyboard, and put it in A
KEYUP		equ 0x3E69	; Wait for key release
INPUTSTRING	equ 0x3E6C	; Read a string into buffer at DE

; POLL status bits
BIT_RECV	equ 2
BIT_DISCON	equ 1
BIT_CONN	equ 0

;;; Socket Types (added by me from socket.h)

AF_INET		equ 0
SOCK_STREAM	equ 1
SOCK_DGRAM	equ 2
SOCK_RAW	equ 3

;;; System Variables (only available while paged in)

v_column	equ 0x3F00
v_row		equ 0x3F01
v_rowcount	equ 0x3F03
Client code. Basically the code from Tutorial 3 on the wiki with minor tweaks, with an additional custom CLEAR42 to place a title bar and use colours other than white on blue provided by the ROM. I am using a local IP at this point.

Code: Select all

; A simple TCP client - this goes along with the following:
; http://spectrum.alioth.net/doc/index.php/Spectranet:_Tutorial_3

        include "labels.asm"

        org 33000               ; Start with RAND USR 33000

        call CLS42		; clear the screen and set cursor

        ; Open the socket - this simply allocates the resources we
        ; need, and gives us an identifier (file descriptor) for the socket.
        ld c, SOCK_STREAM       ; We want a stream - i.e. TCP socket.
        ld hl, SOCKET           ; Routine to call in ROM - SOCKET.
        call HLCALL
        jp c, ERROR             ; Exit on error.
        ld (v_sockfd), a        ; Save the socket.

        ; Connect to the remote host. First print a message saying
        ; that this is what we're trying.
	ld ix, PRINT42
        ld hl, STR_connect      
        call IXCALL

        ; ...now connect
        ld a, (v_sockfd)        ; Get the socket file descriptor
        ld de, ip_buffer        ; DE = the address of the IP address in memory
        ld bc, 4000		; we want to connect to port 4000
        ld hl, CONNECT          ; call the CONNECT routine
        call HLCALL
        jp c, ERROR             ; carry is set on error.

        ; Now send some data - 'ping' which will elicit a response.
        ld a, (v_sockfd)        ; Get the socket file descriptor
        ld de, STR_send         ; String to send
        ld bc, 4		; which is 18 bytes long
        ld hl, SEND             ; to be passed to the ROM SEND routine
        call HLCALL
        jr c, ERROR

        ; Get the response and print it to the screen. Display a message
        ; saying we're waiting.
	ld ix, PRINT42
        ld hl, STR_receiving
        call IXCALL

        ld a, (v_sockfd)
        ld de, resp_buffer      ; the buffer we want to fill.
        ld bc, 1024             ; up to 1K at a time
        ld hl, RECV             ; and use the ROM's RECV routine
        call HLCALL
        jr c, ERROR
        
        ; Make sure the returned buffer has a null on the end for
        ; when we go to print it.
        ld hl, resp_buffer
        add hl, bc              ; BC contains the number of bytes received.
        ld (hl), 0              ; put a NULL on the end

	ld ix, PRINT42
        ld hl, resp_buffer      ; and print the data we received
        call IXCALL

        ld a, (v_sockfd)        ; Get the socket fd
        ld hl, CLOSE            ; and close it.
        call HLCALL

	ld ix, PRINT42
        ld hl, STR_done         ; Print 'Done'
        call IXCALL
        ret

; The next two routines are support routines - exit on error, and print
; a string.
ERROR
	ld ix, PRINT42
        ld hl, STR_error        ; Error string
        call IXCALL              ; print it
        ld a, (v_sockfd)
        and a                   ; is the socket set?
        ret z                   ; no.. but if it is
        ld hl, CLOSE            ; clean up the socket
        call HLCALL
        ret        

;; Clear the screen, set PRINT42 cursor and set the title bar.
CLS42
	ld a, 7
	out (254), a		; white border
	ld hl, 16384
	ld de, 16385
	ld bc, 6144
	ld (hl), l
	ldir
	ld (hl), 71		; bright 1/black paper/white ink
	ld bc, 32
	ldir
	ld (hl), 56		; white paper/black ink
	ld bc, 735
	ldir
	call PAGEIN
	ld a,9
	ld (v_column), a
	xor a
	ld (v_rowcount), a
	ld hl, 16384
	ld (v_row), hl 
        ld hl, STR_titlebar	; Title bar string
        call PRINT42		; print it
	call PAGEOUT
	ld hl, 16385
	ld de, stripes

	ld b,8
loop1
	push bc
	push hl
	ld a,(de)	
	ld b,5
loop2
	ld (hl),a
	inc hl
	djnz loop2
	inc de
	pop hl
	call Pixel_Address_Down
	pop bc
	djnz loop1

	ld hl,22529
	ld a,66
	ld (hl),a
	inc hl
	ld a,86
	ld (hl),a
	inc hl
	ld a,116
	ld (hl),a
	inc hl
	ld a,101
	ld (hl),a
	inc hl
	ld a,104
	ld (hl),a
	
	ret 

stripes
	defb %00000001
	defb %00000011
	defb %00000111
	defb %00001111
	defb %00011111
	defb %00111111
	defb %01111111
	defb %11111111 

;; Move HL down one pixel line
Pixel_Address_Down
	INC H			; Go down onto the next pixel line
	LD A,H			; Check if we have gone onto next character boundary
	AND 7
	RET NZ			; No, so skip the next bit
	LD A,L			; Go onto the next character line
	ADD A,32
	LD L,A
	RET C			; Check if we have gone onto next third of screen
	LD A,H			; Yes, so go onto next third
	SUB 8
	LD H,A
	RET   

;; Message Strings. Note that the strings are C strings - they are all null terminated.
STR_send        defb "ping",0
STR_titlebar	defb "SpectraMUD v1.0",10,0
STR_looking     defb "Looking up remote host...\r",0
STR_connect     defb "Connected...",10,0
STR_receiving   defb "Receiving data...",10,0
STR_error       defb "Failed!\r",0
STR_done        defb "Done.\r",0

;; Variables
v_sockfd        defb 0          	; storage for socket file descriptor
ip_buffer       defb 192,168,0,43    	; IP address
resp_buffer                     	; put the response after everything else
4 x

User avatar
Guesser
Microbot
Posts: 159
Joined: Wed Nov 15, 2017 2:35 pm
Contact:

Re: ZX Spectrum Multi User Dungeon (MUD)

Post by Guesser »

I'm just an enthusiastic user and advocate (well I've committed a few minor patches). :)
1 x

User avatar
MonkZy
Microbot
Posts: 189
Joined: Thu Feb 08, 2018 1:01 pm

Re: ZX Spectrum Multi User Dungeon (MUD)

Post by MonkZy »

Another update on progress.

Big breakthroughs with client-server communications. I have coded a keyboard entry routine. I have coded a main client loop which polls the socket for incoming data, prints data when it arrives, reads keyboard into a buffer and sends the buffer when enter is hit. So basically a fully working (crude) telnet/MUD client.



Apologies for the odd flashes, my desktop grabber is a bit iffy. I also forgot to move my mouse pointer aside. :oops:

ToDo's are :

A text scrolling routine. I am currently using the PRINT42 routine from the SpectraNet ROM. This is great for testing but scrolls the screen in 1/3rds, I want to scroll at least an 8 pixel row at a time. I can put back my title banner once I have a scroll routine working. I also need to add a delete key to the keyboard input.

Text filtering. I need to filter some codes such as the upside-down question mark. I need to add carriage returns to stop words being cut in half due to the 80 column formatting of CircleMUD.

Better error handling. The error routine is vague. I can use the SpectraNet flags to determine what error occurred and print an appropriate message.

Tidy up the MUD files.
Some of the MUD file texts can be re formatted to fit a 42 column display more elegantly.

Future Possibilities :

A 10kb text buffer which can be scrolled back with the up cursor key.

Coupling the MUD server with a TNFS file server and have location images. Use a control code in the MUD descriptions that can point to files on the file system. Scroll the images in with the text.

Customized GUI for shops, combat etc.

The Code :
SpoilerShow
labels. asm

Code: Select all

;;; Defined Labels

; Hardware page-in entry points
PAGEIN		equ 0x3FF9
PAGEOUT		equ 0x007C
HLCALL		equ 0x3FFA
IXCALL		equ 0x3FFD

; Jump table entry points
SOCKET		equ 0x3E00	; Allocate a socket
CLOSE		equ 0x3E03	; Close a socket
LISTEN		equ 0x3E06	; Listen for incoming connections
ACCEPT		equ 0x3E09	; Accept an incoming connection
BIND		equ 0x3E0C	; Bind a local address to a socket
CONNECT		equ 0x3E0F	; Connect to a remote host
SEND		equ 0x3E12	; Send data 
RECV		equ 0x3E15	; Receive data 

POLL		equ 0x3E1E	; Poll a list of sockets
POLLALL		equ 0x3E21	; Poll all open sockets
POLLFD		equ 0x3E24	; Poll a single socket
GETHOSTBYNAME	equ 0x3E27	; Look up a hostname
PUTCHAR42	equ 0x3E2A	; 42 column print write a character
PRINT42		equ 0x3E2D	; 42 column print a null terminated string
CLEAR42		equ 0x3E30	; Clear the screen and reset 42-col print

LONG2IPSTRING	equ 0x3E39	; Convert a 4 byte big endian long to an IP
IPSTRING2LONG	equ 0x3E3C	; Convert an IP to a 4 byte big endian long
ITOA8		equ 0x3E3F	; Convert a byte to ascii
RAND16		equ 0x3E42	; 16 bit PRNG

GETKEY		equ 0x3E66	; Get a key from the keyboard, and put it in A
KEYUP		equ 0x3E69	; Wait for key release
INPUTSTRING	equ 0x3E6C	; Read a string into buffer at DE

; POLL status bits
BIT_RECV	equ 2
BIT_DISCON	equ 1
BIT_CONN	equ 0

; POLL events/revents bit field
POLLCON		equ 1		; Host has connected to listening socket (not used in spectraMUD)
POLLHUP		equ 2		; The remote host closed the connection
POLLIN		equ 4		; Data is ready to be received
POLLNVAL	equ 128		; An error occurred during polling

;;; Socket Types (added by me from socket.h)

AF_INET		equ 0
SOCK_STREAM	equ 1
SOCK_DGRAM	equ 2
SOCK_RAW	equ 3

;;; System Variables (only available while paged in)

v_column	equ 0x3F00
v_row		equ 0x3F01
v_rowcount	equ 0x3F03
main code.

Code: Select all

; A simple TCP client - this goes along with the following:
; http://spectrum.alioth.net/doc/index.php/Spectranet:_Tutorial_3

        include "labels.asm"

        org 33000               ; Start with RAND USR 33000

        call CLS_42		; clear the screen and set cursor

        ; Open the socket - this simply allocates the resources we
        ; need, and gives us an identifier (file descriptor) for the socket.
        ld c, SOCK_STREAM       ; We want a stream - i.e. TCP socket.
        ld hl, SOCKET           ; Routine to call in ROM - SOCKET.
        call HLCALL
        jp c, Error             ; Exit on error.
        ld (v_sockfd), a        ; Save the socket.

        ; Connect to the remote host. First print a message saying
        ; that this is what we're trying.
	ld ix, PRINT42
        ld hl, STR_connect      
        call IXCALL

        ; ...now connect
        ld a, (v_sockfd)        ; Get the socket file descriptor
        ld de, ip_buffer        ; DE = the address of the IP address in memory
        ld bc, 4000		; we want to connect to port 4000
        ld hl, CONNECT          ; call the CONNECT routine
        call HLCALL
        jp c, Error             ; carry is set on error.

	;; Send a handshake ' ', print a message notifying user of this.
	ld ix, PRINT42
        ld hl, STR_handshake      
        call IXCALL

        ;; Now send some data - ' ' which will elicit a response. 
	;; not sure why, but you must do this to get the MUD to send the motd/login page.
        ld a, (v_sockfd)        ; Get the socket file descriptor
        ld de, STR_send         ; String to send
        ld bc, 1		; which is 1 bytes long
        ld hl, SEND             ; to be passed to the ROM SEND routine
        call HLCALL
        jp c, Error

	ld b,0			; use B to count a short delay between socket polls

	ld hl,23560		; LAST K system variable.
	ld (hl),b		; put null value there.

	;;; And so begins an endless loop 	
Client_Loop
	;; check poll delay
	ld a,b
	cp 0
	jp nz, Skip_Poll

	ld b,255		; reset the delay counter
	push bc			; preserve B for delay counter

	;; Poll the socket for ready data

	ld a, (v_sockfd)	; socket file descriptor
	ld hl, POLLFD
	call HLCALL		; zero flag is set if sockfd is not ready. Flags returned in C
	
	jp z, Skip_Print	; skip printing if sockfd is not ready

	ld a, c			; load the events flags into A
	cp POLLIN		; check if data is ready to be recieved
	jp nz, Poll_Error	; no data, most likely the host has closed the connection.
	
	call Print_Text		; print incoming text
Skip_Print
	pop bc

Skip_Poll
	push bc			; preserve B for delay counter
 
	;; Read the keyboard

	ld hl,23560		; LAST K system variable.
	ld a,(hl)
	cp 0			; check for null
	jr z, non_printable	; no key has been pressed, loop back
	ld b,0
	ld (hl),b		; put null value there.

	cp 13
	jp z, return		; check if ENTER has been pressed

	cp 32
	jp c, non_printable	; check if input char is out of ASCII range (will be a cursor,inverse video or delete)

	cp 123
	jp nc, non_printable	; check if input char is out of ASCII range (not sure if this is possible)

	ld b,a			; put input char into B for safekeeping

	ld a,(kb_size)
	cp 86
	jp z,non_printable	; check if the key buffer is full

	inc a
	ld (kb_size),a		; increase the buffer size variable by one byte

	ld a,b			; retrieve the input char
	ld hl,(kb_pointer)	; load HL with the key buffer pointer address
	ld (hl),a		; store the char in the buffer
	inc hl			; increment the buffer pointer
	ld (kb_pointer),hl	; store the buffer pointer

	ld hl,PUTCHAR42
	call HLCALL

non_printable
	pop bc			; retrieve B for delay counter
	dec b			; decriment the delay counter
	jp Client_Loop

	;; We have an ENTER, send the command to the MUD!!
return
	
	ld de,(kb_pointer)	; load DE with the key buffer pointer address
	ld hl,STR_terminator	; load HL with the CR+LF string address
	ld bc, 2
	ldir			; store the chars in the buffer
	
	ld a, (kb_size)
	ld c,a
	ld b,0			; load BC with the byte length of the buffer
        ld a, (v_sockfd)        ; load A with the socket file descriptor
        ld de, kb_buffer	; load DE with the address of the keyboard buffer
        
        ld hl, SEND             ; to be passed to the ROM SEND routine
        call HLCALL
        jp c, Error

	;; reset the keyboard buffer
	xor a			; Load A with zero
	ld hl,kb_buffer
	ld b,86		; fill the buffer with zeros
reset_loop
	ld (hl),a		; store a zero into buffer
	inc hl
	djnz reset_loop

	ld bc,kb_buffer
	ld (kb_pointer),bc	; reset the key buffer pointer

	ld a,8
	ld (kb_size),a		; reset the key buffer size

	pop bc			; retrieve B for delay counter
	ld b,0			; reset the delay counter

	;; print a carriage return
	ld a,10
	ld hl,PUTCHAR42
	call HLCALL

	jp Client_Loop

	;; Exit cleanly to BASIC from main loop
exit
        call Close_Socket

	ld ix, PRINT42
        ld hl, STR_done         ; Print 'Done'
        call IXCALL
	pop bc			; empty the stack for a clean return to BASIC
        ret	

Print_Text
        ld a, (v_sockfd)
        ld de, resp_buffer      ; the buffer we want to fill.
        ld bc, 1024             ; up to 1K at a time
        ld hl, RECV             ; and use the ROM's RECV routine
        call HLCALL
  
        ; Make sure the returned buffer has a null on the end for
        ; when we go to print it.
        ld hl, resp_buffer
        add hl, bc              ; BC contains the number of bytes received.
        ld (hl), 0              ; put a NULL on the end

	ld ix, PRINT42
        ld hl, resp_buffer      ; and print the data we received
        call IXCALL

	ld ix, PRINT42
        ld hl, kb_buffer	; print the text input buffer
        call IXCALL

	ret



	;; Error while polling, if the host closed the connection message the user
Poll_Error
	cp POLLHUP		; check if host has closed the connection
	jp nz,Error		; it must be an error during polling
	ld ix, PRINT42
        ld hl, STR_host_closed	; Host has closed the connection string
        call IXCALL             ; print it
	pop bc			; empty the stack for a clean return to BASIC
	jp Close_Socket		

	;; Exit on error, and print a vague string.
Error
	ld ix, PRINT42
        ld hl, STR_error        ; Error string
        call IXCALL             ; print it

	;; Close the socket and exit
Close_Socket
        ld a, (v_sockfd)
        and a                   ; is the socket set?
        ret z                   ; no.. but if it is
        ld hl, CLOSE            ; clean up the socket
        call HLCALL
        ret        

	;; Clear the screen, set PRINT42 cursor and set the title bar.
CLS_42
	ld a, 7
	out (254), a		; white border
	ld hl, 16384
	ld de, 16385
	ld bc, 6144
	ld (hl), l
	ldir
	ld (hl), 56		; bright 1/black paper/white ink (71 for banner)
	ld bc, 32
	ldir
	ld (hl), 56		; white paper/black ink 
	ld bc, 735
	ldir
	call PAGEIN
	ld a,0			; 9 for banner
	ld (v_column), a
	xor a
	ld (v_rowcount), a
	ld hl, 16384
	ld (v_row), hl

	jp skip_banner		; skipping banner for now
 
        ld hl, STR_titlebar	; Title bar string
        call PRINT42		; print it
	call PAGEOUT
	ld hl, 16385
	ld de, stripes

	ld b,8
loop1
	push bc
	push hl
	ld a,(de)	
	ld b,5
loop2
	ld (hl),a
	inc hl
	djnz loop2
	inc de
	pop hl
	call Pixel_Address_Down
	pop bc
	djnz loop1

	ld hl,22529
	ld a,66
	ld (hl),a
	inc hl
	ld a,86
	ld (hl),a
	inc hl
	ld a,116
	ld (hl),a
	inc hl
	ld a,101
	ld (hl),a
	inc hl
	ld a,104
	ld (hl),a
skip_banner	
	ret 

stripes
	defb %00000001
	defb %00000011
	defb %00000111
	defb %00001111
	defb %00011111
	defb %00111111
	defb %01111111
	defb %11111111 

	;; Move HL down one pixel line
Pixel_Address_Down
	INC H			; Go down onto the next pixel line
	LD A,H			; Check if we have gone onto next character boundary
	AND 7
	RET NZ			; No, so skip the next bit
	LD A,L			; Go onto the next character line
	ADD A,32
	LD L,A
	RET C			; Check if we have gone onto next third of screen
	LD A,H			; Yes, so go onto next third
	SUB 8
	LD H,A
	RET   

;; Message Strings. Note that the strings are C strings - they are all null terminated.
STR_send        defb 32,"ping",13,10,0
STR_titlebar	defb "SpectraMUD v1.0",10,0
STR_cursor	defb 10,">",0
STR_looking     defb "Looking up remote host...",10,0
STR_connect     defb "Connecting to MUD...",10,0
STR_handshake   defb "Sending handshake...",10,0
STR_host_closed	defb 10,"The host has closed the connection!",0
STR_error       defb 10,"An error has occured!",0
STR_done        defb 10,"Done.",0
STR_not_null	defb "nn",0
STR_terminator	defb 13,10	; CR+LF

;; Keyboard buffer and variables (reserve 84 bytes, two lines of text)
kb_buffer
	defb 0,0,0,0,0,0,0,0,0,0
	defb 0,0,0,0,0,0,0,0,0,0
	defb 0,0,0,0,0,0,0,0,0,0
	defb 0,0,0,0,0,0,0,0,0,0
	defb 0,0,0,0,0,0,0,0,0,0
	defb 0,0,0,0,0,0,0,0,0,0
	defb 0,0,0,0,0,0,0,0,0,0
	defb 0,0,0,0,0,0,0,0,0,0
	defb 0,0,0,0
	defb 0,0			; extra 2 bytes for CR+LF termination
kb_pointer
	defw kb_buffer
kb_size
	defb 2

;; Variables
v_sockfd        defb 0          	; storage for socket file descriptor
ip_buffer       defb 192,168,0,43    	; IP address
resp_buffer                     	; put the response after everything else
2 x

User avatar
Einar Saukas
Dynamite Dan
Posts: 1193
Joined: Wed Nov 15, 2017 2:48 pm

Re: ZX Spectrum Multi User Dungeon (MUD)

Post by Einar Saukas »

This is looking great!

It has the characteristics of a project that may continue to evolve over time. For this reason, I suggest you move this project to Github and post a link here, instead of posting copies of your code directly.

This will have many advantages. People will be able to easily find the latest version (instead of searching through many posts), it will take a single click to download and try it, it will give your project more visibility, you will have a good place to add an intro page explaining it later, we will be able to add it to ZXDB later with a direct link to it, and so on.
1 x

Quazar
Berk
Posts: 5
Joined: Tue Jun 16, 2020 2:28 pm

Re: ZX Spectrum Multi User Dungeon (MUD)

Post by Quazar »

This sounds very interesting, I'll have to keep an eye on it! (I was playing/coding on a MUD way, way back in 1992 or so, seriously addictive stuff!). While I don't have a Spectranet for my ZX Spectrums I do have the Next dev board and could also help with adapting the client for the SAM Coupé as I gave that an ethernet connection with my Trinity interface.
1 x

User avatar
MonkZy
Microbot
Posts: 189
Joined: Thu Feb 08, 2018 1:01 pm

Re: ZX Spectrum Multi User Dungeon (MUD)

Post by MonkZy »

Einar Saukas wrote:
Mon Jul 06, 2020 2:06 pm
For this reason, I suggest you move this project to Github and post a link here, instead of posting copies of your code directly.
I will look into this. I am not a trained programmer so I am never confident my code is acceptable. I strive to get a piece of code to work, and gain satisfaction when it does what I want it to do. I am never certain I took the best approach. Github does look like a great way to organize and present a project, so I will set one up soon. Thanks for the advice.

Quazar wrote:
Mon Jul 06, 2020 8:52 pm
(I was playing/coding on a MUD way, way back in 1992 or so, seriously addictive stuff!).
The MUD server side of things is pretty overwhelming to be honest. There is so much to learn just to get something basic working. I will try to get some Spectrum themed areas working but most likely I will run a slightly altered default CircleMUD (Midgaard, New Thalos etc.) server for any testing. The base world on CircleMUD is pretty huge and fun to explore if you have never played in it. I have never played a stock DikuMUD so it is new content to me. Ultimately I want to have an area aimed at Spectrum users, with a portal into the circleMUD content. I may ask for advice when I get to that stage. I am totally new to the server side of MUD's. I only played in heavily populated MUD's and never got high enough in a guild to get close to editing the content. Wrote a bunch of client side scripts and macro's though. Aye, can be quite addictive.

An eventual NEXT and SAM client would be cool :D I really wanted a SAM back in the day. By the time I had the income to buy one, the ship had sailed and I went the Amiga route.
0 x

User avatar
ketmar
Dizzy
Posts: 92
Joined: Tue Jun 16, 2020 5:25 pm

Re: ZX Spectrum Multi User Dungeon (MUD)

Post by ketmar »

MonkZy wrote:
Tue Jul 07, 2020 1:16 am
Einar Saukas wrote:
Mon Jul 06, 2020 2:06 pm
For this reason, I suggest you move this project to Github and post a link here, instead of posting copies of your code directly.
I will look into this. I am not a trained programmer so I am never confident my code is acceptable.
you don't have to publish some "perfect" code. you don't have to be a "trained professional". that's the whole idea of FOSS -- start something you want to do, and other people will join and help you if they'll like it.

look at a source code repository as if it is just a backup archive. that archive doesn't have to be in a "perfect" state. and there is no authority to "accept" your code (besides Z80, of course ;-). you just copying your working files to a remove server (with some comments). most people will never expect your commits to be always perfect.

sorry for this long text. i just wanted to encourage you a little. ;-)
0 x

Post Reply