Hola,

Ok, i've decided to try my hands at improving my knowledge of assembly by creating a version of "MUD" (aka Multi user dungeon/domain/d... whatever). More specifically I'm trying to improve my knowledge of working with *structures* and *pointers* in assembly.

Basic Set-Up
I want to create the environment so that the user would see on the screen:

---- hypothetical output ----

You're in the Temple.
There is no one here with you.
There is nothing on the floor.

move east

You're in the North Square
There is no one here with you.
There is nothing on the floor.

move south

You're in the South Square
There is no one here with you.
There is nothing on the floor.

move west

You can't go in that direction.

---- end ----

Now the problem is I'm looking for a robust way to create the room locations in such a way so that it can be easily expanded and have many properties (hence a struct)... but I don't really want to use a multi dimension array to represent it...

More like:

struct Location
{
string name;
string description;

// what room lies in each direction
//if the location is NULL then there is not room in
// that direction
Location * north;
Location * south;
Location * east;
Location * west;
Location * northeast;
Location * southeast;
Location * northwest;
Location * southwest;
Location * up;
Location * down;
}

Basically the way I figured it would be that the player struct would have a pointer the location struct and by checking that structure above find out where other room were...

structure Being
{
string name; // name of this being
string article; // article for being e.g. "a" "an"
string pronoun; // pronoun for being, e.g. "he" "she" "it"
string possessive; // possesive pronoun, e.g. "his", "her", "its"
string sex; // sex of this being

int gold; // how much gold this being has

Location * location; // where this being is
}

The problem is I don't know how to port my code in c++ to assembly... and I was hoping that someone would understand what I was trying for a maybe help me write a "small example" so I could get a grasp of this concept better... Inotherwords, how can I do this more robustly?

Again if someone has/had and example of a small text based world example I'd appreciate a look

Sliver
Posted on 2002-02-17 23:47:08 by Sliver
Since, I'm still new to Direct3d or OpenGl, I may not be of help but since you mentioned that it's text based I suggest you do a linked list or an array of structures, you can modify a doubly linked list to make it octuple linked list(8 Directions - N, E, W, S, NE, NW, SE, SW). But It would be better if you do a quadruple linked list/Array of structures (4 Directions - N, E, W, S) - less complicated.



player STRUCT
Name DB 20 DUP(?)
Desc DB 20 DUP(?)
Location DD ?
player ENDS


Location must be an address in memory. This is usually the address or pointer in memory that was allocated by HeapAlloc or GlobalAlloc or VirtualAlloc. You have make the player start at the root node or the first allocated memory.




items STRUCT
name DB 20 DUP(0)
desc DB 20 DUP(0)
Effect DD ?
items ENDS

rooms STRUCT
N DD ?
E DD ?
W DD ?
S DD ?
Desc DB 50 DUP(?)
RmItem items<>

;You could create an array of items.

player ENDS


If I have the time, I could code one, if you want. I know I didn't explain much up here, since there are a lot of things to consider and If I do It'll be a long one. I'll make a follow up with the code it will be just four rooms and only four directions just to give you an example.

Hmm!!! looks like Ultima to me but text based.

Happy Coding!!!
Posted on 2002-02-18 00:25:40 by stryker
Thanks for the help so far...

What I'm looking for doesn't have to be dynamic... I'm going to assume that I hav only 9 rooms...


[NULL] [NULL] [NULL] [NULL] [NULL]
[NULL] [Room1] [Room2] [Room3] [NULL]
[NULL] [Room4] [Room5] [Room6] [NULL]
[NULL] [Room7] [Room8] [Room9] [NULL]
[NULL] [NULL] [NULL] [NULL] [NULL]


Given this type of setup...

I want within the player structure to have a pointer to the "players location" in the world...

The location structure would contain pointers for all 8 possible directions and if the value is not NULL then it would contain the address of the adjecent room...

I know how to do this in C++, but I'm absolutely confused doing to in assembly


Sliver
Posted on 2002-02-18 00:55:55 by Sliver
Yes, it would be very easy, It's so hard to explain right now, but I'll try to code up one using an array of structures to give you an example. I'll be back with the code. Oh!!! no classes tomorrow. Nice!!!
Posted on 2002-02-18 01:00:15 by stryker
umberg6007... Your help is very much appreciated...
I don't think I can sleep until I solve this problem :(

I editted my last comments to reflect more clearly what I'm trying to do...

Sliver

ps. 2am here in New York and I should be getting up for 9 am classes too...
Posted on 2002-02-18 01:04:22 by Sliver
The included zip file should do the trick. The asm file is not optimized and still lacks most aspects of the game but it should help you solve the movements of your game. I suggest you make the included .gif file as your guide. You can exploit it if you want. There's no sophisticated algorithm, everything's hard coded to make it easier for you to understand.

Happy Coding!!!

P.S. Oops I forgot, tomorrows president's day, so no classes :)
Posted on 2002-02-18 03:01:59 by stryker
first off...

Thank you very much for your great application...
:):):)
I need all the help I can get, so I appreciate it

Second...

I figured that both your method and mine aren't that condusive to making very large applications... So do you think that this might not be done a more productive way?

I'm including my source and app (the app -- mainly because I hardcoded the values to demonstrate that I was passing the pointer to the location structure)

Well anyway here it is... I explained a bit more of what I'm doing in the source...

Sliver

ps. run it first to get a feel for what it is doing (because of the hardcoded values)
Posted on 2002-02-18 03:27:32 by Sliver
OMG, you hard coded the memory locations? Uurp sorry, It's late it's 1:30 a.m here, I'll check it out tomorrow. But anyway, I'll see what I can do to improve it. I need sleep!!!

P.S. I never coded that way before, I always have my own GUI with me. Never tried using debug.
Posted on 2002-02-18 03:36:19 by stryker
I have an Idea, this is from my chess program in java. The concept is to think there are 2 points on one square namely the x and the y axis.

So we have to create structure like this:



player struct
xAxis DD ?
yAxis DD ?
player ends


so each square also has an axis point



[NULL] [NULL] [NULL] [NULL] [NULL]
[NULL] [0, 0] [0, 1] [0, 2] [NULL]
[NULL] [1, 0] [1, 1] [1, 2] [NULL]
[NULL] [2, 0] [2, 1] [2, 2] [NULL]
[NULL] [NULL] [NULL] [NULL] [NULL]


I'm sure this can be done in a very productive way. Making the user enter how many x and y grids he/she wants, will help us determine our borders. Assuming he/she choses a 2 x 3 grid:



[NULL] [NULL] [NULL] [NULL]
[NULL] [0, 0] [0, 1] [NULL]
[NULL] [1, 0] [1, 1] [NULL]
[NULL] [2, 0] [2, 1] [NULL]
[NULL] [NULL] [NULL] [NULL]


Starting at room 0 (0, 0) the player chose the following movements:

left: (0, 0) subtract 1 from y = -1, check if this value is < 0 or =2 if it is, this is an invalid move.
right: (0, 0) add 1 to y = 1, check if this value is < 0 or = 2, no it's not, so change the player's current x and y locations to (0, 1)
right: (0, 1) add 1 to y = 2, check if this value is < 0 or = 2, if it is, this is an invalid move.

If the player choses to move down or up, you have to add/subtract 1 from the user's current location.

So here's a rundown:

Moving from left to right and vice versa: check the y axis value if it's < 0 or = 2
Moving from up to right and vice versa: check the x axis value if it's < 0 or = 3

I'm sure you get my point and I know there's a little twist on the concept but it's the best solution I can think of. Tell me if you have questions.

Happy Coding!!!


I'll leave this up to you. I'm sure you can code this way.


And finally, I forgot to add this, create a table look up, when
the user lands on a room E.G. a room with axis point
(0, 0) this will resolve to 0 and then you can go and calculate the
equivalent structure and print the data of the structure.



location struct
description DB 50 DUP(0)
location ends
Posted on 2002-02-18 11:18:55 by stryker
Ok this is the code to move around the map that I've created for now...

valid keys are:
e, w, n, s

any other key will exit

Sliver



;-------------------------------------------------------------------------------
; loc.asm
;-------------------------------------------------------------------------------
; [email]sliver55@ix.netcom.com[/email] (Sliver)
;-------------------------------------------------------------------------------
; Assemble : ml /c /coff loc.asm
; Link : link /SUBSYSTEM:WINDOWS loc.obj
;-------------------------------------------------------------------------------


.386
.model flat, stdcall
option casemap: none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\masm32.inc
include \masm32\include\debug.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\debug.lib

; ------------
; Local macros
; ------------
print MACRO Quoted_Text:VARARG
LOCAL Txt
.data
Txt db Quoted_Text,0
.code
invoke StdOut,ADDR Txt
ENDM

input MACRO Quoted_Prompt_Text:VARARG
LOCAL Txt
LOCAL Buffer
.data
Txt db Quoted_Prompt_Text,0
Buffer db 128 dup(?)
.code
invoke StdOut,ADDR Txt
invoke StdIn,ADDR Buffer,LENGTHOF Buffer
mov eax, offset Buffer
ENDM

cls MACRO
invoke ClearScreen
ENDM

InitMap PROTO
Main PROTO

.data

LOCATIONS struct
n dd 0
s dd 0
e dd 0
w dd 0
rname db 16 DUP (0)

LOCATIONS ends


;g_Location is initialized with a 'room number', but will later contain the
;pointer to the actual structure location
g_Locations LOCATIONS {0,3,1,0, "Room 0"}, {1,1,2,0,"Room 1"}, {2,5,2,1,"Room 2"},\
{0,6,3,3, "Room 3"}, {4,7,5,4,"Room 4"}, {2,5,5,4,"Room 5"},\
{3,6,7,6, "Room 6"}, {4,7,8,6,"Room 7"}, {8,8,8,7,"Room 8"}

.code

start:

invoke Main
invoke ExitProcess,0

; #########################################################################
; Example: Room 1 contains a number corresponding to a 'room location'
; After InitMap runs the Location structure for room 1 will contain pointers
; to all the adjecent location structure. IF THERE IS NO ROOM IN A CERTAIN DIRECTION
; then the location structure will point to itself... So when you see
; for room 0 { 0, 3, 1, 0} it means that for:
; North ( room 0 points to ) itself,
; South ( room 0 points to ) room 3,
; East ( room 0 points to ) room 1,
; West ( room 0 points to ) itself
;
; Room set-up
; 0 1 2
; 3 4 5
; 6 7 8
; #########################################################################
InitMap proc

push esi
ASSUME esi:PTR LOCATIONS
lea esi, g_Locations

push edi
ASSUME edi:PTR LOCATIONS
lea edi, g_Locations

mov ecx, 1

@@:
push ecx

mov eax, [esi].n
mov ecx, SIZEOF LOCATIONS
mul ecx

lea edx, [edi+eax]
mov [esi].n, edx

mov eax, [esi].s
mov ecx, SIZEOF LOCATIONS
mul ecx

lea edx, [edi+eax]
mov [esi].s, edx

mov eax, [esi].e
mov ecx, SIZEOF LOCATIONS
mul ecx

lea edx, [edi+eax]
mov [esi].e, edx

mov eax, [esi].w
mov ecx, SIZEOF LOCATIONS
mul ecx

lea edx, [edi+eax]
mov [esi].w, edx

add esi, SIZEOF LOCATIONS

pop ecx
inc ecx
cmp ecx, 10
jne @B
@@:
ASSUME edi:nothing
pop edi
ASSUME esi:nothing
pop esi

ret

InitMap endp

Move proc

Move endp

Main proc

invoke InitMap

.data
inbuffer db 32 DUP(0)
location dd 0
.code

print " ",13,10
print "[Room0] <-> [Room1] <-> [Room2]",13,10
print " | | ",13,10
print "[Room3] [Room4] <-> [Room5]",13,10
print " | | ",13,10
print "[Room6] <-> [Room7] <-> [Room8]",13,10
print " ",13,10

push esi
ASSUME esi:PTR LOCATIONS
lea esi, g_Locations

mov location, esi

lea edx, [esi].rname
invoke StdOut, edx

ASSUME esi:nothing
pop esi

nextone:
invoke StdIn,ADDR inbuffer,LENGTHOF inbuffer ;get input

mov esi,offset inbuffer

;check input for cr or lf

@@:
lodsb
.if (al == 'n')
push esi
ASSUME esi:PTR LOCATIONS
mov esi, location


print "Moving North...",13,10
mov esi, [esi].n
lea edx, [esi].rname
invoke StdOut, edx

mov location, esi
ASSUME esi:nothing
pop esi
.elseif (al == 's')
push esi
ASSUME esi:PTR LOCATIONS
mov esi, location

print "Moving South...",13,10
mov esi, [esi].s
lea edx, [esi].rname
invoke StdOut, edx

mov location, esi
ASSUME esi:nothing
pop esi
.elseif (al == 'e')
push esi
ASSUME esi:PTR LOCATIONS
mov esi, location

print "Moving East...",13,10
mov esi, [esi].e
lea edx, [esi].rname
invoke StdOut, edx

mov location, esi
ASSUME esi:nothing
pop esi
.elseif (al == 'w')
push esi
ASSUME esi:PTR LOCATIONS
mov esi, location

print "Moving West...",13,10
mov esi, [esi].w
lea edx, [esi].rname
invoke StdOut, edx

mov location, esi
ASSUME esi:nothing
pop esi
.else
ret
.endif
jmp nextone

ret

Main endp

end start


Posted on 2002-02-18 14:08:55 by Sliver
I tried it and it works great! Cool :alright:
Posted on 2002-02-18 14:18:36 by stryker

Hola,

struct Location
{
string name;
string description;

// what room lies in each direction
//if the location is NULL then there is not room in
// that direction
Location * north;
Location * south;
Location * east;
Location * west;
Location * northeast;
Location * southeast;
Location * northwest;
Location * southwest;
Location * up;
Location * down;
}

Basically the way I figured it would be that the player struct would have a pointer the location struct and by checking that structure above find out where other room were...

structure Being
{
string name; // name of this being
string article; // article for being e.g. "a" "an"
string pronoun; // pronoun for being, e.g. "he" "she" "it"
string possessive; // possesive pronoun, e.g. "his", "her", "its"
string sex; // sex of this being

int gold; // how much gold this being has

Location * location; // where this being is
}



Hi sliver,
well i'd like to propose an idea about the structure design

U wanna create the location and the beings as objects and so on should address the location they stay in
But this way to list all the beings, objects and other things that stay in a room u've to check all the beings, objects,... u've created to discover which r the ones present in ur room and u've to do this every time u change room and if u've a quite big number of beings, obejcts and so on its quite hard work 4 ur machine
What about putting inside the location a pointer to a list of entities created this way:

struct entity
{
entity* next_entity;
void* entity_object;
int entity_type;
}

Every location has to be its entity list which lists all the entities
inside the room
Entities r beings, objects,... and so on
U put the pointer to ur being, object structure in the entity_object field and u put a ID for the entity type in the entity_type field
so u r able to deal with the structure pointed by the entity_object

See ya
NikDH
Posted on 2002-02-19 18:29:13 by NikDH
Originally posted by NikDH

struct entity
{
entity* next_entity;
void* entity_object;
int entity_type;
}

Every location has to be its entity list which lists all the entities
inside the room
Entities r beings, objects,... and so on
U put the pointer to ur being, object structure in the entity_object field and u put a ID for the entity type in the entity_type field
so u r able to deal with the structure pointed by the entity_object


I can't say I follow you're idea completely, but I'll explain what I was thinking...

First this is how I moved around rooms (I think I'm going to use a variation of this to create weapons and armor -- however items seem to be a bit different)...

I created an array of structures (each of which is a room location)...

Within the structure is a list of directions (North, South, East, ect..) which are changed to pointers to the rooms that are connected to when the program is run.

A pointer to the location that the player is in can be found within the "player" structure. So here is what else is contained in the location structure...

The location struture also contains a list of pointers for the items present in the room... Much like the way I reference the connecting rooms...

Therefore if a battleaxe is in the room with the player the computer only checks what room the player is in and goes to that location structure... the location structure contains a pointer to the weapon or armor type that is in that location too...



location struct
room_items dd {6},{2},{4},{1}
location ends


Where:
1 = club
2 = short sword
etc.

These will be pointers to the weapons only (I use numbers for clarity sake).

Therefore, (and this is the key part) I don't need to make multiple instances of the same weapon for someone to use... All players and creatures will reference the same weapon structure. So 100 people or creatures can be using a battle axe, but I only need to reference that one structure (mainly because weapons tend to not change in their specifications).

The problem:

I don't know what to do about certain types of "items"... Mainly because some items "run out"... Like a "torch" for example...

A torch should run for about 5 minutes and then burn out... but using the same structure as a reference would mean that I can't change the structure... I don't want to have to allocate space for 300 torch structure needlessly...

Maybe I'll put some form of timer in the player structure to keep track of these types of "timing" prblems...

Anyway, I always appreciate the help (and since I always post all my source it would be beneficial to the rest of the community if we could all put something together... great learning exercise :)

Sliver

ps. I'm intrested to know exactly what you mean... if you want to modify my source and repost it... I'd love to see where you are going with it...

pps. I just thought... creatures will be annoying...
I may have to allocate "Actual" space from the heap for them... seeing they can't use the same structure... i'dunno
Posted on 2002-02-19 22:22:36 by Sliver
If I have the time, I'll code up one, since I'm always interested in an RPG like game, even though it's text based, the idea still rocks ;)

Who says dungeon and dragons(papers and pencils) is boring? :grin:
Posted on 2002-02-19 22:25:48 by stryker
If you want to create the data statically, then macros would make it very readable and automate most the the pointer offset stuff. Let me give a small example of ideal syntax (assuming readablity is a plus):
Room 5, <This is a cool place to be!>

; note compass directions below:
Room_Links 5, \
1, 2, 3, \
4, 6, \
7, 8, 9
Room_Items 5, <Book, Lamp, Pen>

...this would create a data structure like...

Room_5:
dd offset RoomDesc_5
dd offset Room_1,offset Room_2,offset Room_3
dd offset Room_4,offset Room_6,offset Room_7
dd offset Room_8,offset Room_9
dd offset RoomItemsList_5

RoomDesc_5 db "This is a cool place to be!"

RoomItemsList dd offset items_5_0,offset items_5_1,offset items_5_2

items_5_0 db "Book",0
items_5_1 db "Lamp",0
items_5_2 db "Pen",0
You can see how a little macro coding has a big pay off, and will maybe help organize the data a little better? Also, you could keep the same map layout and change the macros to match your code as it develops. ;)
Posted on 2002-02-19 23:00:36 by bitRAKE
Hey, Our MACRO king :grin: I'll code up using my x and y idea and I will try to attempt to do an octuple/quadruple linked list, ha ha never heard of it before. :grin:
Posted on 2002-02-19 23:04:27 by stryker
Ok here is an updated version... :-)

What it includes:
-Better optimized
-Now you can move in all 8 possible directions
N,S,E,W,NW,NE,SW,SE
-gave rooms the ability to have weapons (only 1.. but more shouldn't be too difficult)
-new look as well

I'm sure that isn't all -- just gonna have to download it to see it..

Can't post the source on this page anymore... it's 200 more lines than it was the last time I posted it...
:):):)

Sliver

ps. umberg6007 I can't wait to see it (I think I may need to implement some form of what your doing so I could use all the help...)

pps. BitRAKE I think you're right about the macro thing... IF you download the code maybe you could tell me where it might come in the most useful...

-----EDIT----
deleted the last download because it had the debug window in it

so here is a new one
Posted on 2002-02-20 01:36:14 by Sliver




location struct
room_items dd {6},{2},{4},{1}
location ends


Where:
1 = club
2 = short sword
etc.

The problem:

I don't know what to do about certain types of "items"... Mainly because some items "run out"... Like a "torch" for example...

A torch should run for about 5 minutes and then burn out... but using the same structure as a reference would mean that I can't change the structure... I don't want to have to allocate space for 300 torch structure needlessly...

Maybe I'll put some form of timer in the player structure to keep track of these types of "timing" prblems...

Anyway, I always appreciate the help (and since I always post all my source it would be beneficial to the rest of the community if we could all put something together... great learning exercise :)


Hi sliver,
ur idea about careful use of resources is good :)
The solution at ur prob should be this one:
u can create objects with a common section and a private section
such as dll that have a common code section and as many data sections as many process have loaded the dll
The torch object is a structure with a method inside:

strcut torch_personal_data
{
int fuel; /* remaining fuel of the torch */
time_t time_start; /* time u've lit the torch */
int some_other_info;
}

strcut torch
{
/* All the common data of every torch */
int light_power;
...

/* This function is returning a handle u can use to access the info
about ur personal torch */
void* turnOn();
int get_remaining_light_time(void* htorch);
}

void* turnOn()
{
void* temp;
temp = malloc(sizeof(torch_personal_data));
torch_personal_data->fuel = init_value;
/* some other init stuff of the torch */
/* create a timer object that will signal when the torch has run out of fuel */
}

int get_remaining_light_time(void* htorch)
{
int temp;
long deltat;
deltat = gettime() - time_start;
/* u can calc easily the remenaing fuel with this data */
}

Well the code should has some errs coz i'm in a little hurry now
but the idea should be quite clear

See ya
NikDH
Posted on 2002-02-20 13:04:31 by NikDH
Real quick... Someone explain to me why this won't work...

What I'm doing:
My location structure contains a pointer to items in the rooms...
I wrote a proc to take that item on the floor and put it into the players structure, but it doesn't work...



GetItemFromRoom proc

LOCAL temp:DWORD
xor edx, edx

;Check for weapons lying on the floor
push edi
ASSUME edi:PTR WEAPONS
lea edi, g_Weapons

push esi
ASSUME esi:PTR LOCATIONS
mov esi, loc

.if (edi == [esi].ritem)
print "There is nothing lying on the floor.",10,13
.else
;moving the pointer of the item on the floor to edi
mov edi, [esi].ritem

.endif

ASSUME esi:nothing
pop esi

push esi
ASSUME esi:PTR PLAYER
mov esi, g_Player

;I get the error here saying instruction
;operands must be the same size
mov [esi].weapon, edi ; <---Error here

ASSUME esi:nothing
pop esi

ASSUME edi:nothing
pop edi

ret
GetItemFromRoom endp

;Structures:
LOCATIONS struct
north dd 0
south dd 0
east dd 0
west dd 0
neast dd 0
nwest dd 0
seast dd 0
swest dd 0
rname db 24 DUP (0)
numberofritem dd 0
ritem dd 2 DUP (0)
LOCATIONS ends

PLAYER struct
pname db 24 DUP (0)
weapon dd 0
pid dd 0
PLAYER ends

WEAPONS struct
wname db 24 DUP (0)
wid dd 0
WEAPONS ends
Posted on 2002-02-20 23:28:15 by Sliver
This is the problem with assembly :)



push esi
ASSUME esi:PTR PLAYER
mov esi, g_Player


it should have been



push esi
ASSUME esi:PTR PLAYER
[B]LEA[/B] esi, g_Player


Spent like 30 minutes tracking this down
Posted on 2002-02-20 23:37:00 by Sliver