grid system....

Elexxorine
13 Jun 2005, 14:21
im' making a HUGE game world for my game TBC, and was thinking over the old grid system, is there a working example i could use, or any other good system that's better.... ( and trust me: it's stupidly huge, first area is 57,600 squares big so far :o , might make it smaller, though...) thanks :D

MaDbRiT
13 Jun 2005, 21:39
Elexxorine wrote

trust me: it's stupidly huge, first area is 57,600 squares big so far



Yeah, I'd agree with that - '57600 squares' (240x240? treated as seperate locations presumably) is STUPIDLY :shock: large... Seriously, think again - your players will hate you with a passion if you get even remotely close to that figure... :roll:

That said, setting up a grid structure for movement within a room is not at all hard to do. Here's a 5 x 5 grid (25 locations) - to make it bigger or rectangular you'd just change the xpos/ypos maximums to anything you like.

In my code the player enters the grid centre bottom row and can mooch about (exits appear disappear as needed).

' Grid Locations

define game <Game Name>

asl-version <350>

gametype singleplayer

game version <1.0>
game author <MaDbRiT>
game copyright <© 2005 AGB>
game info <Enter any additional information about this game here.>

start <StartRoom>

startscript {
set numeric <xpos;3>
set numeric <ypos;1>
}

end define

define room <StartRoom>

look <It looks very familiar...>

north {
do <MakeExits>
goto <gridroom>
}

end define

define room <GridRoom>
script {
outputon
exec <look>
}
command <north> {
outputoff
exec <north;normal>
}
command <south> {
if (%xpos%<>3) or (%ypos%<>1) then outputoff
exec <south;normal>
}
command <west> {
outputoff
exec <west;normal>
}
command <east> {
outputoff
exec <east;normal>
}
end define

define room <North_Dummy>
script {
inc <ypos>
do <MakeExits>
goto <GridRoom>
}
end define

define room <South_Dummy>
script {
dec <ypos>
do <MakeExits>
goto <GridRoom>
}
end define

define room <East_Dummy>
script {
inc <xpos>
do <MakeExits>
goto <GridRoom>
}
end define

define room <West_Dummy>
script {
dec <xpos>
do <MakeExits>
goto <GridRoom>
}
end define


define procedure <MakeExits>
outputoff
create exit north <GridRoom;>
create exit south <GridRoom;>
create exit east <GridRoom;>
create exit west <GridRoom;>
if (%xpos% <>1) then create exit west <GridRoom; West_Dummy>
if (%xpos% <>5) then create exit east <GridRoom; East_Dummy>
if (%ypos% <>1) then create exit south <GridRoom; South_Dummy>
if (%ypos% <>5) then create exit north <GridRoom; North_Dummy>
if (%xpos% = 3) and (%ypos% =1) then create exit south <GridRoom; StartRoom>
property <Gridroom;alias=Location X=%xpos%, Y=%ypos%>
end define

define text <intro>
Enter intro text here
end define

define text <win>
Enter win text here
end define

define text <lose>
Enter lose text here
end define


Should you need to drop objects in grid locations - storing them in a dummy room and allocating them x / y variables to check and move them as required is easy.

Al (MaDbRiT)

davidw
13 Jun 2005, 22:21
Ah, another uber-epic-massive game that everyone knows will never be finished.

First there was Shadow Projekt, then there was Business Tycoon (or whatever it was called), now there's this...

The list just grows.

Elexxorine
14 Jun 2005, 10:07
yeah, thanks madbrit. how can i make bigger areas with lots of blockages. eg.

+-----+-----+-----+-----+-----+
¦ ¦ ¦ ¦ ¦ ¦
+-----+-----+-----+-----+-----+
¦ ¦ ***¦ ¦ ¦ ¦
+-----+-----+-----+-----+-----+
¦ ¦ ¦ ¦ ***¦ ¦
+-----+-----+-----+-----+-----+
¦ ¦ ¦ ¦ ¦ ¦
+-----+-----+-----+-----+-----+
¦ start ¦
*** blockage.


i can't see how to do it.

MaDbRiT
14 Jun 2005, 10:31
Elexxorine wrote

how can i make bigger areas with lots of blockages



Well if you want inaccessible 'squares' in your grid, I'd not use the system I gave above at all. :!:

The above method works great with minimal coding required for (say) wandering about in a featureless desert of forest or whatever, but if you want a "maze" (for want of a better word) you have to cater for too many exceptions for it to be a practical exercise.

For a maze I'd use a grid based on a simple numeric array. I won't try to explain it here because it isn't easy without an example and I'm at work presently so I don't have time to code one.

I'll knock up a simple example later, assuming "real life" doesn't get in the way...

Al (MaDbRiT)

paul_one
14 Jun 2005, 15:21
IIRC it's not of any good use right now because you can't destroy exit's. Objects or rooms I think you can, but exits you can't (last time I looked).

Got in the way of another thing I was doing, so had to have a conditional in the north/south/east/west.
But yeah, I used a numeric array too.

Elexxorine
15 Jun 2005, 10:03
i have no idea how to use arrays. please help me there too... :lol:

francisstokes
15 Jun 2005, 11:20
an array is just like var, except u can store alot more numbers in them and reference them by one name.

and how to use them is in the quest documentation.

Gary Brown
15 Jun 2005, 18:08
You might wanna rethink that many locations in your mud. It's up to you, but generally, 10,000 rooms is considered a rather large mud. There are ways to write a smaller area, and just make it "feel" bigger. Check out some old infocom games for ideas. Just a thought.

Gary

steve the gaming guy
22 Jun 2005, 20:45
MaDbRiT wrote:
The above method works great with minimal coding required for (say) wandering about in a featureless desert of forest or whatever, but if you want a "maze" (for want of a better word) you have to cater for too many exceptions for it to be a practical exercise.

For a maze I'd use a grid based on a simple numeric array. I won't try to explain it here because it isn't easy without an example and I'm at work presently so I don't have time to code one.

I'll knock up a simple example later, assuming "real life" doesn't get in the way...

Al (MaDbRiT)


Al,
I had received some great help a while back on how to build a grid for a large area instead of creating dozens of rooms.
This is a similar concept, however, it is in the form of hallways in a maze. I believe it's about 40 rooms something similar to:

X    X     
XX X XXXXXX
X X X
XXXXXXXXX


The example above represents about 23 rooms. I made that up at random for example purposes where "X" equals a room. Would this be a good enough example or is that too big for a quickie example coding?

MaDbRiT
23 Jun 2005, 08:39
Steve wrote

Would this be a good enough example or is that too big for a quickie example coding



I got half way through coding a second grid example (suitable for mazes) and then got distracted by work...

I'll try and finish it and post here soonest.

Al (MaDbRiT)[/quote]

MaDbRiT
23 Jun 2005, 11:13
Steve;

OK then

Here's the 10 x 10 cell (100 location) grid the example below is intended to implement.



The grey areas are inaccessible cells and it should be obvious that links to the outside of the grid are at cell 4 (the exit the player is trying to get to) and cell 95 (the entrance).

As should be obvious from the code below, I'm using a numeric array called 'grid' to store a single number which is a binary encoded representation of the available exits from each grid location.

One room 'gridroom' represents all the visitable cells.

Obviously I had to code 'special case' exits for the entrance and exit cells of the grid array - otherwise there's not a lot to it.

You can easily 'tweak' this code to get more grid locations if needed and setting which cells cannot be visited is just a question of calling the "KillAccess" procedure with the cell number as a parameter.

If anything needs further explanation, please ask.


' Grid of locations within one room

define game <Grid Demo>

asl-version <350>

gametype singleplayer

game version <1.0>
game author <MaDbRiT>
game copyright <© 2005 AGB>
game info <Demo>

start <StartRoom>

startscript {
do <MakeGrid> 'This builds a 10 x 10 grid (with hard boundaries)

' Calling 'KillAccess' procedure with the cell number as a parameter closes all
' (N,S,E & W) entrances to the cell referenced.

do <KillAccess(1)>
do <KillAccess(3)>
for <x;5;11> do <KillAccess(%x%)>
for <x;20;26> do <KillAccess(%x%)>
for <x;28;30> do <KillAccess(%x%)>
for <x;42;62;10> do <KillAccess(%x%)>
for <x;44;84;10> do <KillAccess(%x%)>
for <x;82;83> do <KillAccess(%x%)>
for <x;46;47> do <KillAccess(%x%)>
for <x;49;50> do <KillAccess(%x%)>
do <KillAccess(57)>
for <x;66;70> do <KillAccess(%x%)>
do <KillAccess(77)>
do <KillAccess(89)>
for <x;96;99> do <KillAccess(%x%)>

'Open additional (special) Exits to south in Cell 95 and to north in cell 4
'These are the entry to / exit from the gridroom maze

set <grid[95];2>
set <grid[4];10>
}


end define

define room <StartRoom>
alias <a small, gloomy room.>
look <The room is completely bare and featureless.>
north {
set <gridPos;95>
do <makeExits>
goto <gridroom>
}

end define

define room <exitroom>
alias <the treasure chamber>
look <Its a bit dark and spooky.>
south {
set <gridPos;4>
do <makeExits>
goto <gridroom>
}
end define


define room <GridRoom>
script {
' msg <DEBUG: Exit code for this (%gridPos%) room is = %grid[gridPos]%>
}
alias <a maze of seemingly identical corridors>

command <north> {
set <gridPos;%gridPos%-10>
if (%gridpos%<>-6) then {
do <makeExits>
goto <GridRoom>
}
else goto <exitroom>
}

command <south> {
set <gridPos;%gridPos%+10>
if (%gridpos%<>105) then {
do <makeExits>
goto <GridRoom>
}
else goto <startroom>
}

command <east> {
set <gridPos;%gridPos%+1>
do <makeExits>
goto <GridRoom>
}

command <west> {
set <gridPos;%gridPos%-1>
do <makeExits>
goto <GridRoom>
}

end define

define room <dummy>

end define

define procedure <MakeGrid>
set numeric <gridPos;0>

' ** Set Basic boundaries of 10 x 10 grid

' ** Set exit north OFF for top row of grid
for <i;1;10> {
set numeric <grid[i];1>
}

' ** Set exit south OFF for bottom row of grid
for <i;91;100> {
set numeric <grid[i];4>
}

' ** Set exit east OFF for right row of grid
for <i;10;100;10> {
set numeric <grid[i];%grid[i]%+2>
}

' ** Set exit west OFF for left of grid
for <i;1;91;10> {
set numeric <grid[i];%grid[i]%+8>
}
end define

define procedure <makeExits>
create exit north <GridRoom;dummy>
create exit east <GridRoom;dummy>
create exit south <GridRoom;dummy>
create exit west <GridRoom;dummy>
set numeric <gridVal;%grid[gridPos]%>

if (%gridVal% >7) then {
create exit west <GridRoom;>
set <gridVal;%gridVal%-8>
}

if (%gridVal% >3) then {
create exit south <GridRoom;>
set <gridVal;%gridVal%-4>
}

if (%gridVal% >1) then {
create exit east <GridRoom;>
set <gridVal;%gridVal%-2>
}

if (%gridVal% >0) then {
create exit north <GridRoom;>
}
end define

define procedure <KillAccess>
set numeric <BlockBox;$parameter(1)$>

' In this procedure we need to modify the boxes bordering the chosen box
' rather than the box to be blocked itself. First up is to block the
' exit to this box from the south.
' Move down a row.
set <BlockBox;%BlockBox%+10>
set numeric <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8> ' Discard WEST bit
if (%ExitsBlocked% >3) then set <ExitsBlocked;%ExitsBlocked%-4> ' Discard SOUTH bit
if (%ExitsBlocked% >1) then set <ExitsBlocked;%ExitsBlocked%-2> ' Discard EAST bit
if (%ExitsBlocked% =0) then set <grid[BlockBox];%grid[BlockBox]%+1> ' Set NORTH bit if not set

'Now the access from the north.
set <BlockBox;%BlockBox%-20>
' IF Makes sure we're not in the top row, (we can ignore this stage if we are)
if (%BlockBox%>10) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8> ' Discard WEST bit
if (%ExitsBlocked% <4) then set <grid[BlockBox];%grid[BlockBox]%+4> ' Set SOUTH bit if not set
}

'Now the access from the west
set <BlockBox;%BlockBox%+9>

make sure we aren't in the leftmost columnn
set numeric <isLeftCol;0>
for <i;10;100;10> {
if (%BlockBox%=%i%) then set <isLeftCol;1>
}
if (%isLeftCol%<>1) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8> ' Discard WEST bit
if (%ExitsBlocked% >3) then set <ExitsBlocked;%ExitsBlocked%-4> ' Discard SOUTH bit
if (%ExitsBlocked% <2) then set <grid[BlockBox];%grid[BlockBox]%+2> ' Set EAST bit if not set
}

'Now the access from the east
set <BlockBox;%BlockBox%+2>

make sure we aren't in the rightmost columnn
set numeric <isRightCol;0>
for <i;1;91;10> {
if (%BlockBox%=%i%) then set <isRightCol;1>
}
if (%isRightCol%<>1) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% <8) then set <grid[BlockBox];%grid[BlockBox]%+8> ' Set WEST bit if not set
}

end define

define text <intro>
A demonstration of using one Quest room to represent a grid of locations, in this example a 10 x 10 (100 cell) grid, with lots of the cells inaccessible to form a "maze"
end define

define text <win>
Enter win text here
end define

define text <lose>
Enter lose text here
end define


Oh yeah - this is a cut n'paste runnable providing you are careful to make sure the word-wrap from the firum doesn't mess it up

Al (MaDbRiT)

MaDbRiT
23 Jun 2005, 11:20
TWIMC

If anyone thinks its would be useful to them, I could re-work the grid/maze code as given in the example to be a Quest Library at some time in the future.

Al (MaDbRiT)

Elexxorine
23 Jun 2005, 12:19
i kinda don't get it, its the arrays..... :cry: help

steve the gaming guy
23 Jun 2005, 15:22
Wow, that's amazing. I don't fully understand it yet...but still amazing. I will try to incorporate that once I understand how to change the numbers based on my needs.
If I have trouble with it, I'll ask again!

Thanks!

MaDbRiT
23 Jun 2005, 16:14
Elexxorine wrote:

I kinda don't get it, its the arrays..... help



It isn't that bad really. :-)

I've used a numeric array called 'grid', which has 100 elements, each of these corresponds to a cell in the 10 x 10 grid of cells illustrated at the top of my post.

e.g. grid[14] refers to the cell numbered 14 in my drawing.

With a grid system, I need to store the information regarding exits for each cell in the grid. Look at cell 14, it has exits North, West & East (but not south).

By using a bit of binary thinking, I store in the array grid[14] one number which represents all four exits. I build the number like so:

start from 0
if there is an exit north +1
if there is an exit east +2
if there is an exit south +4
if there is an exit west +8

So the resulting number for the exits in cell 14 is stored in the grid array, by setting grid[14] = 11.

This means the exits for all 100 cells (potentially 300 odd exits) are stored in an array of 100 numbers. The array is therefore just a simple numeric array, with each element containing a number between 0 and 15.

If you need explanations of how the binary bit for the exits works - that's a whole different topic.

Al (MaDbRiT)

steve the gaming guy
23 Jun 2005, 20:33
Hmmm, I've been looking this over and I thought I had it until about part way through this section. I'm sort of understanding the KillAccess (1), etc... all the way up until 30.




do <KillAccess(1)>
do <KillAccess(3)>
for <x;5;11> do <KillAccess(%x%)>
for <x;20;26> do <KillAccess(%x%)>
for <x;28;30> do <KillAccess(%x%)>


....but then I don't understand why you go from 42 to 62 and throw a 10 in there...


for <x;42;62;10> do <KillAccess(%x%)>


....same here but in regards to the 84, why wasn't it like the original rows where you wrote 20-26 as 20;26. Couldn't it have been written 82;83?

for <x;44;84;10> do <KillAccess(%x%)>
for <x;82;83> do <KillAccess(%x%)>


I was trying to create my code based on this and I just don't really know where to start because I don't know what it means.

MaDbRiT
23 Jun 2005, 21:45
Steve wrote;

....but then I don't understand why you go from 42 to 62 and throw a 10 in there...



(in respect of this code)

  for <x;42;62;10> do <KillAccess(%x%)> 


it's because I don't want ALL the cells from 42 thru 62 to be disabled.

With a for loop, there is an optional third parameter known as STEP.. an example will make this clearer

for <x;42;62> do <KillAccess(%x%)> 


I'm sure you know that in this case KillAccess will be called with 42 as a parameter, then 43 then 44 and so on until it reaches 62 - at which point the loop will end. However if we include the third STEP parameter, say of 10 like so...

for <x;42;62;10> do <KillAccess(%x%)> 


at each iteration the counter (x) is incremented by 10, the STEP specified, so in fact 'KillAccess' will be called with 42 as a parameter, then 52 then finally 62 and the loop ends. If you look at my diagram you will see how this makes sense. I'm using both styles of for loops to cover all the cells I want to "block" with as little code as possible.

As a matter of fact, in a 'for loop' you can specify negative values as a STEP, have your START higher than your END and count backwards if you need to as well, but that's by the by. :lol:

Hope this helps.

Al (MaDbRiT)

Elexxorine
24 Jun 2005, 10:08
can you make me a general code for the array: like putting bits explaining each and every bit so i know what to put in myself.... sorry it's confusing.... :roll:

MaDbRiT
24 Jun 2005, 12:00
Elexxorine asked;

can you make me a general code for the array



Sorry, I don't really understand what you mean by a 'general code'. Arrays are just a general purpose coding construct to be used however we as coders see fit.

The array I'm using in the above code really is nothing more than an absolutely "bog-standard" numeric array. I'm doing some rather more advanced stuff in terms of what I'm storing in the array and how I'm using it to represent rooms, but that is more to do with creative application of the basic 'array' construct, rather than anything to do with 'how to use arrays' in general.

Asking for a 'general code' for the array construct is a bit like asking 'how do I use a computer?', it invites the response 'how do you use it to do what?' because an Array is a multi purpose tool, just like a computer.

I'll try to explain what an array is, and hopefully the penny will drop!

First of all, you need to understand what a variable is - I'm fairly sure you must, but just in case.

A variable is a named storage space for a literal (either numeric or a string)

So by doing this

set numeric <myvariable;10>


we assign the name 'myvariable' to a storage space and in that space store the number 10. We can then read the stored value (10) back by way of the variable name, or indeed change (vary) it. If you like visualising this, think of a large box, with the name 'myvariable' written on it containing 10 'wotsits'.

Key fact: Variables exist to give us a way to assign meaningful names to storage space.

Now sometimes you need a whole lot of similar variables. Lets assume you have 50 bottles in your game and each one has a different amount of beer in it. You could have 50 variables, named 'bottle1', bottle2, bottle3 and so on to store the amounts of beer in each. However if you want to (say) add up how much beer you have in total, the code becomes horrendous to read, e.g.

set numeric <totalBeer;%bottle1% + %bottle2% + %bottle3%+ %bottle2% + %bottle3%+ %bottle2% + %bottle3%+ %bottle4% + %bottle5%+ %bottle6% + %bottle6%+ %bottle8% + %bottle9%+ %bottle10% + %bottle11%+ %bottle12% + %bottle13%+ %bottle14% + %bottle15%+ %bottle16% + %bottle17%+ %bottle18% + %bottle19%+ %bottle20% + %bottle21%+ %bottle22% + %bottle23%+ %bottle24% + %bottle25%+ %bottle26% + %bottle27%+ %bottle28% + %bottle29%+ %bottle30% + %bottle31%+ %bottle32% + %bottle33%+ %bottle34% + %bottle35%+ %bottle36% + %bottle37+ %bottle38% + %bottle39%
+ %bottle40% + %bottle41%+ %bottle42% + %bottle43%+ %bottle44% + %bottle45%+ %bottle46% + %bottle47%+ %bottle48% + %bottle49%+ %bottle50%>


There has to be a better way, right? Well there is and it's using an array.

Going back to our simple variable 'box' imagine we put dividers into it so that it could hold 50 beer bottles and write the name BOTTLES on the side of the box. We then number each of the 50 compartments in the box with a number, starting from 1 and ending at 50.

An array works like that divided box. We can use each of the compartments as a seperate variable called 'bottles[n]' - where 'n' is the number of the compartment in the box we want to work with.

This pays off when we want to work with all the bottles - as in finding the total beer in them, instead of that horrible long chain addition code we have above we can do this...

for <n;1;50> {
set numeric <totalbeer;%totalbeer% + %bottles[n]%>
}


That's the beauty of arrays, you can use a loop to generate the index number (n) and it makes for much less (and much neater!) code.

Imagine you needed to find which of the beer bottles had the most beer in them... if they were individual variables that would be a horrible job requiring loads of error prone if-then tests, with an array you can do it in one loop...


set numeric <mostBeer;0>
set numeric <maxBeer;0>
for <n;1;50> {
if (%bottles[n]% >%maxbeer%) then {
set numeric <maxBeer;%bottles[n]%>
set numeric <mostbeer;%n%>
}
}

'This code will return the array index of the fullest bottle in the variable 'mostbeer'.


The above ought to explain what arrays are, and how they can be useful to us as coders. Exactly what uses we put them to is down to individual taste and ability.

Al (MaDbRiT)

Elexxorine
24 Jun 2005, 12:23
ok i get arrays, there like a labled 'box' of variables, now can you go back and explain the logic of the maze (like the 0,1,2,4,8 thing) and also do you use 'n' like in your expaample in the real code?

(ps. going to alton towers for weekend, be back on monday.... :D )

MaDbRiT
24 Jun 2005, 15:18
Elexxorine;

Do I use n in the real code? It doesn't matter - in the example n is a place holder for either a literal or a variable..

You can use

%array[34]%


which will return the value of the 34th element, or you can use a variable, say 'myvariable' is currently = 25

%array[myvariable]% 


which will return the value of the 25th element.

What you use is up to you and the circumstances!

can you go back and explain the logic of the maze (like the 0,1,2,4,8 thing)



It's making use of simple binary maths.

We are used to counting in decimal (units of ten) using the digits 0-9 and then repeating them. In binary we only use the digits 0 & 1. It's easier to see how this works with a diagram:



You should be able to see from the above how 4 binary digits (a.k.a. bits) can hold any number from 0-15. The useful part in this case is that you can allocate a direction to each bit, and then decide that when that bit=1 the exit in the corresponding direction is open when it's 0 the exit is closed, something like this:



In the above example, we can read off that having exits North, East and West will generate the decimal number 11. This single number is therefore holding the status of all four possible exit directions, so we can store that in the array element relevant to the location.

Later on, when a player enters the location, a little bit of logic is used to break the stored number (11 in this case) back into its four binary bits and the exits are created accordingly.

You are not tied to just using four bits of course, I only needed four to accomplish this task, but you can keep going 'ad-infinitum', commonly you use 8 bits (a.k.a. a 'byte') and then multiple bytes.

Al (MaDbRiT)

steve the gaming guy
24 Jun 2005, 17:23
Wow!

I'm pretty sure I understand what your <42;62;10> means now! Since blocks 42, 52 and 62 were in the same column (and 10 cells apart), you told the program that those three blocks were inaccessible.

I'm just about completely understood on your arrays explanation.

And the binary thing, Wow! That's cool! What I'm looking at in your diagram is that depending on your total number, tells the program where the exits are.
So if your total was one (1), then your exit would be W.
If your total was fifteen (15), then all four exits are open.
If your total was nine (9), then your exits are N and W.
...and so on...

Am I right?

MaDbRiT
24 Jun 2005, 18:49
Steve wrote:

I'm pretty sure I understand what your <42;62;10> means now! Since blocks 42, 52 and 62 were in the same column (and 10 cells apart), you told the program that those three blocks were inaccessible.



Exactly that :-) The for loop's 'STEP' parameter is useful don't you think?

I'm just about completely understood on your arrays explanation.



i've been using arrays so long I found it difficult to think back to when I didn't understand them either (Sinclair ZX81 era!) - I hoped my compartments in a box comparison would prove a decent explanation.

And the binary thing, Wow! That's cool! What I'm looking at in your diagram is that depending on your total number, tells the program where the exits are.
So if your total was one (1), then your exit would be W.
If your total was fifteen (15), then all four exits are open.
If your total was nine (9), then your exits are N and W.
...and so on...

Am I right?



You have the idea 'spot on' - of course it would have helped understanding considerably if I had not reversed the bit order for the exits in my explanation from that I use in the demo code :oops:

That's what comes of answering things 'blind' when at work, I could have SWORN I'd done it the same way in both !

I've now fixed that by making the diagram agree to the demo...

Take a look again now and hopefully it'll make even better sense.


Al (MaDbRiT)

steve the gaming guy
25 Jun 2005, 03:38
Yes, thank you...very helpful...

Alright, I'm trying to break this down. In the following code from your demo, what does the 2 and 10 mean?

   set <grid[95];2> 
set <grid[4];10>


What does the -6 and 105 in this part of the code?

define room <GridRoom>
script {
' msg <DEBUG: Exit code for this (%gridPos%) room is = %grid[gridPos]%>
}
alias <a maze of seemingly identical corridors>

command <north> {
set <gridPos;%gridPos%-10>
if (%gridpos%<>-6) then {
do <makeExits>
goto <GridRoom>
}
else goto <exitroom>
}

command <south> {
set <gridPos;%gridPos%+10>
if (%gridpos%<>105) then {
do <makeExits>
goto <GridRoom>
}
else goto <startroom>
}




...and the 91's?


define procedure <MakeGrid>
set numeric <gridPos;0>

' ** Set Basic boundaries of 10 x 10 grid

' ** Set exit north OFF for top row of grid
for <i;1;10> {
set numeric <grid[i];1>
}

' ** Set exit south OFF for bottom row of grid
for <i;91;100> {
set numeric <grid[i];4>
}

' ** Set exit east OFF for right row of grid
for <i;10;100;10> {
set numeric <grid[i];%grid[i]%+2>
}

' ** Set exit west OFF for left of grid
for <i;1;91;10> {
set numeric <grid[i];%grid[i]%+8>
}
end define


Ok, that's all my asking for now. I was really trying to figure this out to the very last detail. I am currently working on an 8x8 grid and I just needed to see what these certain numbers were for as you entered them above. ..

MaDbRiT
25 Jun 2005, 08:47
Steve

Alright, I'm trying to break this down. In the following code from your demo, what does the 2 and 10 mean?



set <grid[95];2>
set <grid[4];10>


Well if you look at the grid you will see that locations 95 and 4 are 'special' in the sense that as well as providing exits to the other locations INSIDE the grid, they also each have an exit to rooms OUTSIDE the grid.

Because early on I have blocked all the north exits in the top row cells of the grid and all the south exits in the bottom row (using loops) I now need to tweak the exits for these two rooms so that they 'show' ways out of the grid when the player is in the grid location.

So I set grid[95] to 2, which means only exit 2 (EAST) is blocked, effectively this opens the way south I had blocked when I set all the bottom row south exits off earlier.

Setting grid[4] to 10 has a similar effect, it means only exits EAST and WEST are blocked, so effectively opens the exit north, out of the grid/maze.

You might notice that in my working example I'm using a set bit to indicate a BLOCKED exit not an OPEN one, this is simply because there are less blocked exits than open ones so I have less setting of bits to do. If your maze/grid has more blocked than open, you might prefer to reverse this and use the set bit to indicate open (as I did in my later binary explanation) it doesn't REALLY matter which way you go on this., I'm just lazy enough to use the shorter way wherever possible :-)

What does the -6 and 105 in this part of the code?



Well when the player moves around in the grid, as he selects a direction his destination cell is calculated and exits are set accordingly.

If he is in grid[4] and chooses to go North (that special exit I created as explained above) up a row means his location will be -10 from where he is now (theoretically the impossible grid[-6]).

So here I test whether a move north would put the player in grid[-6] - if not then he isn't in grid[4] and we process a move around the grid as normal, if he IS in grid[4] then we move him to 'exitroom' because he has found a way out of the grid.

So grid[95] is the other 'special' location - the only bottom row cell that allows a move SOUTH, same idea in that down a row = +10, so a move south here would have the player in grid[105] (which we don't want.)
Instead if he selects SOUTH from grid[95] we move him back to the start room.

...and the 91's?



These bits of code are just setting the overall boundaries of the 10 x 10 grid. The remarks tell you what each one does as well as i am able to!
e.g.


for <i;91;100> {
set numeric <grid[i];4>
}


 
for <i;1;91;10> {
set numeric <grid[i];%grid[i]%+8>
}


the first loop runs along the bottom row of the grid (every cell from 91 to 100) closing the exit to the south for each location.

the second loop runs down the left hand column of cells (1-91 in steps of 10 = 1,11,21,31 etc) closing the exit WEST for each cell.

The other two are similar working on the top row to kill exits NORTH and the right hand column to kill exits EAST. Basically I am preventing the player 'wandering off the grid or (worse) wandering off the EAST side of the grid and reappearing a row lower on the WEST side ;-)

I was really trying to figure this out to the very last detail. I am currently working on an 8x8 grid and I just needed to see what these certain numbers were for



If you are a 'smart cookie' you will quickly realise that as your required 8 x 8 grid would fit inside my 10 x 10 example, you can use all the 'tricky' code above unaltered. :-)

All you'd need to do is alter two of the four 'Basic Boundaries' to get a working 8 x 8 grid - and then pop in your 'killaccess' cells and tweak the exits to where you want them.

Think about this... Set all the exits SOUTH in row 8 of my grid to blocked - you have 8 usable rows... Set all the exits EAST in column 8 of my grid to blocked and you have 8 usable columns - hey presto an 8 x 8 grid!

something like this;


'  ** Set Basic boundaries of 8 x 8 grid 

' ** Set exit north OFF for top row of grid
for <i;1;8> {
set numeric <grid[i];1>
}

' ** Set exit south OFF for bottom row of grid
for <i;71;80> {
set numeric <grid[i];4>
}

' ** Set exit east OFF for right row of grid
for <i;8;78;10> {
set numeric <grid[i];%grid[i]%+2>
}

' ** Set exit west OFF for left of grid
for <i;1;71;10> {
set numeric <grid[i];%grid[i]%+8>
}


I altered all four, but actually you could safely ignore the loops related to the left and top rows, I did it for neatness.

or-

You could just use KILLACCESS in a loop to block the bottom two rows of my 10x10 and the rightmost two columns - that'll give you an 8 x 8 grid too.

Strictly speaking you'll be wasting a few array elements - but that's no big deal!


Al (MaDbRiT)

steve the gaming guy
26 Jun 2005, 13:21
Ok, here it is. I have it start where you are dropped in at cell [35] marked in red in the center of the maze and there is only one exit the north at cell [5]. The other blue cell [48] is for later in the game where you re-enter the maze. (I'll be working on that part later after I figure out how to get the maze itself working properly.
Below, I've posted the latest version of the code and a picture of what it's supposed to be.
Some of the maze works but eventually, it starts repeating in certain sections and then I get stuck.




' Grid of locations within one room 

define game <Grid Demo>

asl-version <350>

gametype singleplayer

game version <1.0>
game author <MaDbRiT>
game copyright <© 2005 AGB>
game info <Demo>

start <StartRoom>

startscript {
do <MakeGrid> 'This builds a 8 x 8 grid (with hard boundaries)

' Calling 'KillAccess' procedure with the cell number as a parameter

closes all
' (N,S,E & W) entrances to the cell referenced.

do <KillAccess(1)>
do <KillAccess(2)>
do <KillAccess(4)>
for <x;6;7> do <KillAccess(%x%)>
do <KillAccess(9)>
do <KillAccess(12)>
do <KillAccess(19)>
for <x;21;22> do <KillAccess(%x%)>
do <KillAccess(24)>
do <KillAccess(26)>
do <KillAccess(29)>
do <KillAccess(36)>
for <x;39;42> do <KillAccess(%x%)>
do <KillAccess(46)>
do <KillAccess(50)>
do <KillAccess(52)>
do <KillAccess(56)>
do <KillAccess(62)>

'Open additional (special) Exits to south in Cell 95 and to north in

cell 4
'These are the entry to / exit from the gridroom maze

set <grid[5];2>
}


end define

define room <StartRoom>
alias <a small, gloomy room.>
look <The room is completely bare and featureless.>
north {
set <gridPos;27>
do <makeExits>
goto <gridroom>
}
south {
set <gridPos;43>
do <makeExits>
goto <gridroom>
}
west {
set <gridPos;34>
do <makeExits>
goto <gridroom>
}

end define

define room <DoorRoom>
alias <a small, gloomy room.>
look <The room is completely bare and featureless except for a

single door to the north.>


end define


define room <GridRoom>
script {
' msg <DEBUG: Exit code for this (%gridPos%) room is =

%grid[gridPos]%>
}
alias <a maze of seemingly identical corridors>

command <north> {
set <gridPos;%gridPos%-8>
if (%gridpos%<>-3) then {
do <makeExits>
goto <GridRoom>
}
else goto <exitroom>
}

command <south> {
set <gridPos;%gridPos%+8>
' if (%gridpos%<>105) then {
'
' }
' else goto <startroom>
do <makeExits>
goto <GridRoom>
}

command <east> {
set <gridPos;%gridPos%+1>
do <makeExits>
goto <GridRoom>
}

command <west> {
set <gridPos;%gridPos%-1>
do <makeExits>
goto <GridRoom>
}

end define

define room <dummy>

end define

define procedure <MakeGrid>
set numeric <gridPos;0>

' ** Set Basic boundaries of 10 x 10 grid

' ** Set exit north OFF for top row of grid
for <i;1;8> {
set numeric <grid[i];1>
}

' ** Set exit south OFF for bottom row of grid
for <i;71;80> {
set numeric <grid[i];4>
}

' ** Set exit east OFF for right row of grid
for <i;8;78;10> {
set numeric <grid[i];%grid[i]%+2>
}

' ** Set exit west OFF for left of grid
for <i;1;71;10> {
set numeric <grid[i];%grid[i]%+8>
}
end define

define procedure <makeExits>
create exit north <GridRoom;dummy>
create exit east <GridRoom;dummy>
create exit south <GridRoom;dummy>
create exit west <GridRoom;dummy>
set numeric <gridVal;%grid[gridPos]%>

if (%gridVal% >7) then {
create exit west <GridRoom;>
set <gridVal;%gridVal%-8>
}

if (%gridVal% >3) then {
create exit south <GridRoom;>
set <gridVal;%gridVal%-4>
}

if (%gridVal% >1) then {
create exit east <GridRoom;>
set <gridVal;%gridVal%-2>
}

if (%gridVal% >0) then {
create exit north <GridRoom;>
}
end define

define procedure <KillAccess>
set numeric <BlockBox;$parameter(1)$>

' In this procedure we need to modify the boxes bordering the chosen

box
' rather than the box to be blocked itself. First up is to block the
' exit to this box from the south.
' Move down a row.
set <BlockBox;%BlockBox%+8>
set numeric <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8>

' Discard WEST bit
if (%ExitsBlocked% >3) then set <ExitsBlocked;%ExitsBlocked%-4>

' Discard SOUTH bit
if (%ExitsBlocked% >1) then set <ExitsBlocked;%ExitsBlocked%-2>

' Discard EAST bit
if (%ExitsBlocked% =0) then set

<grid[BlockBox];%grid[BlockBox]%+1> ' Set NORTH bit if not set

'Now the access from the north.
set <BlockBox;%BlockBox%-16>
' IF Makes sure we're not in the top row, (we can ignore this stage

if we are)
if (%BlockBox%>8) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8>

' Discard WEST bit
if (%ExitsBlocked% <4) then set

<grid[BlockBox];%grid[BlockBox]%+4> ' Set SOUTH bit if not set
}

'Now the access from the west
set <BlockBox;%BlockBox%+7>

make sure we aren't in the leftmost columnn
set numeric <isLeftCol;0>
for <i;8;78;10> {
if (%BlockBox%=%i%) then set <isLeftCol;1>
}
if (%isLeftCol%<>1) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8>

' Discard WEST bit
if (%ExitsBlocked% >3) then set <ExitsBlocked;%ExitsBlocked%-4>

' Discard SOUTH bit
if (%ExitsBlocked% <2) then set

<grid[BlockBox];%grid[BlockBox]%+2> ' Set EAST bit if not set
}

'Now the access from the east
set <BlockBox;%BlockBox%+2>

make sure we aren't in the rightmost columnn
set numeric <isRightCol;0>
for <i;1;71;8> {
if (%BlockBox%=%i%) then set <isRightCol;1>
}
if (%isRightCol%<>1) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% <8) then set


<grid[BlockBox];%grid[BlockBox]%+8> ' Set WEST bit if not set
}

end define

define text <intro>
A demonstration of using one Quest room to represent a grid of

locations, in this example a 8 x 8 (64 cell) grid, with lots of the

cells inaccessible to form a "maze"
end define

define text <win>
Enter win text here
end define

define text <lose>
Enter lose text here
end define

MaDbRiT
26 Jun 2005, 18:12
Steve:

In your alterations to my 10 x 10 grid code something has gone awry with your maths/logic and as posted above, you will get some very strange results that don't really match your illustration too well.

Rather than try and explain the wrong bits' - here's the code corrected to make it work:-

' Grid of locations within one room 

define game <Grid Demo>

asl-version <350>

gametype singleplayer

game version <1.0>
game author <MaDbRiT>
game copyright <© 2005 AGB>
game info <Demo>

start <StartRoom>

startscript {
do <MakeGrid> 'This builds a 8 x 8 grid (with hard boundaries)

' Calling 'KillAccess' procedure with the cell number as a parameter

closes all
' (N,S,E & W) entrances to the cell referenced.

do <KillAccess(1)>
do <KillAccess(2)>
do <KillAccess(4)>
for <x;6;7> do <KillAccess(%x%)>
do <KillAccess(9)>
do <KillAccess(12)>
do <KillAccess(19)>
for <x;21;22> do <KillAccess(%x%)>
do <KillAccess(24)>
do <KillAccess(26)>
do <KillAccess(29)>
do <KillAccess(36)>
for <x;39;42> do <KillAccess(%x%)>
do <KillAccess(46)>
do <KillAccess(50)>
do <KillAccess(52)>
do <KillAccess(56)>
do <KillAccess(62)>

'Open additional (special) Exits to north/south in Cell 5

'This is the exit from the gridroom maze

set <grid[5];10>
}


end define

define room <StartRoom>
script {
set <gridPos;35>
do <makeExits>
goto <gridroom>
}
end define

define room <DoorRoom>
alias <a small, gloomy room.>
look <The room is completely bare and featureless except for a single door to the north.>
end define


define room <GridRoom>
script {
msg <DEBUG: Exit code for this (%gridPos%) room is = %grid[gridPos]%>
}
alias <a maze of seemingly identical corridors>

command <north> {
set <gridPos;%gridPos%-8>
if (%gridpos%<>5) then {
do <makeExits>
goto <GridRoom>
}
else goto <doorroom>
}

command <south> {
set <gridPos;%gridPos%+8>
do <makeExits>
goto <GridRoom>
}

command <east> {
set <gridPos;%gridPos%+1>
do <makeExits>
goto <GridRoom>
}

command <west> {
set <gridPos;%gridPos%-1>
do <makeExits>
goto <GridRoom>
}

end define

define room <dummy>

end define

define procedure <MakeGrid>
set numeric <gridPos;0>

' ** Set Basic boundaries of 8 x 8 grid

' ** Set exit north OFF for top row of grid
for <i;1;8> {
set numeric <grid[i];1>
}

' ** Set exit south OFF for bottom row of grid
for <i;57;64> {
set numeric <grid[i];4>
}

' ** Set exit east OFF for right row of grid
for <i;8;64;8> {
set numeric <grid[i];%grid[i]%+2>
}

' ** Set exit west OFF for left of grid
for <i;1;57;8> {
set numeric <grid[i];%grid[i]%+8>
}
end define

define procedure <makeExits>
create exit north <GridRoom;dummy>
create exit east <GridRoom;dummy>
create exit south <GridRoom;dummy>
create exit west <GridRoom;dummy>
set numeric <gridVal;%grid[gridPos]%>

if (%gridVal% >7) then {
create exit west <GridRoom;>
set <gridVal;%gridVal%-8>
}

if (%gridVal% >3) then {
create exit south <GridRoom;>
set <gridVal;%gridVal%-4>
}

if (%gridVal% >1) then {
create exit east <GridRoom;>
set <gridVal;%gridVal%-2>
}

if (%gridVal% >0) then {
create exit north <GridRoom;>
}
end define

define procedure <KillAccess>
set numeric <BlockBox;$parameter(1)$>

' In this procedure we need to modify the boxes bordering the chosen box
' rather than the box to be blocked itself. First up is to block the
' exit to this box from the south.
' Move down a row.
set <BlockBox;%BlockBox%+8>
set numeric <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8>

' Discard WEST bit
if (%ExitsBlocked% >3) then set <ExitsBlocked;%ExitsBlocked%-4>

' Discard SOUTH bit
if (%ExitsBlocked% >1) then set <ExitsBlocked;%ExitsBlocked%-2>

' Discard EAST bit
if (%ExitsBlocked% =0) then set <grid[BlockBox];%grid[BlockBox]%+1> ' Set NORTH bit if not set

'Now the access from the north.
set <BlockBox;%BlockBox%-16>
' IF Makes sure we're not in the top row, (we can ignore this stage if we are)
if (%BlockBox%>8) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8>

' Discard WEST bit
if (%ExitsBlocked% <4) then set <grid[BlockBox];%grid[BlockBox]%+4> ' Set SOUTH bit if not set
}

'Now the access from the west
set <BlockBox;%BlockBox%+7>

make sure we aren't in the leftmost columnn
set numeric <isLeftCol;0>
for <i;8;64;8> {
if (%BlockBox%=%i%) then set <isLeftCol;1>
}
if (%isLeftCol%<>1) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8>

' Discard WEST bit
if (%ExitsBlocked% >3) then set <ExitsBlocked;%ExitsBlocked%-4>

' Discard SOUTH bit
if (%ExitsBlocked% <2) then set <grid[BlockBox];%grid[BlockBox]%+2> ' Set EAST bit if not set
}

'Now the access from the east
set <BlockBox;%BlockBox%+2>

make sure we aren't in the rightmost columnn
set numeric <isRightCol;0>
for <i;1;57;8> {
if (%BlockBox%=%i%) then set <isRightCol;1>
}
if (%isRightCol%<>1) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% <8) then set <grid[BlockBox];%grid[BlockBox]%+8> ' Set WEST bit if not set
}

end define

define text <intro>
A demonstration of using one Quest room to represent a grid of locations, in this example a 8 x 8 (64 cell) grid, with lots of the cells inaccessible to form a "maze"
end define

define text <win>
Enter win text here
end define

define text <lose>
Enter lose text here
end define


The most basic problem was the parts of the code that calculate the boundary cells, they were set for a 10 x 10 grid assuming two rows/columns would not be in use, as a result you renumbering your 8 x 8 grid 1-64 meant the offsets used were all over the place! Essentially you altered some of my code for your 8 x 8 layout but not all of it. :-)

Also, you have dropped the 'player in the centre on the grid and tried to create more 'real' rooms that are inside the grid. You don't need to do this (it is harder for a start!) so I reworked your entry and exit points too.

I've put a little loop into the gridroom which tells you what cell you are in and what the exit code for that cell is - you can thus trundle about the now workking grid and check it against the map to see everything is as drawn.

If you need any help with further developing this idea, please ask.

Al (MaDbRiT)

steve the gaming guy
30 Jun 2005, 21:32
That code works like a dream, MaDbRiT, but now I’m going to muddy up the waters some more.  I wanted to try a couple things with this. In your code, when you finally reach the room with the door, you can’t return south back into the maze. So I thought if I put the south exit of the DoorRoom set to “GridRoom”, it would send me back into the maze. After testing it, it seemed to work, however, if you go further into the maze and try to find the DoorRoom again, you’ll get an error 9 and the game shuts down. (Although it seems to be working currently)

Further, I wanted to make the room that you start out in different so people roaming through the maze would realize that they’re back to the room that they started in. So in other words, I wanted them to get a description similar to “This seems to be the room that you started from since you can see the open grate above you”. Then of course, there should be an object in the room called “grate” so they can examine it if they chose to.

Finally, I wanted to make three rooms [8, 49, 64] (labeled as MonsterRoom, MonsterRoom2, and MonsterRoom3)where a creature would randomly appear in. The discussion of this general idea is in another recent thread but my question relates to the one above in reference to the DoorRoom. Whether or not the creature is in the room, I want the player to be able to “notice” that a creature had been in the room so these three rooms would have their own room descriptions similar to “It appears that in this part of the maze, a creature has recently passed through”
When I began trying to create room 8, I received worse results than when I threw in the “GridRoom” exit on the DoorRoom. I couldn’t even get an exit out of room 8.

Now with all that being said, here is the mutilation of your previously working code trying to insert my own adjustments:


' "Grid Demo"
' Created with QDK 3.53 - UNREGISTERED VERSION

define game <Grid Demo>
asl-version <350>
gametype singleplayer
start <StartRoom>
game author <MaDbRiT>
game version <1.0>
game copyright <© 2005 AGB>
game info <Created with QDK 3.53 - UNREGISTERED EVALUATION VERSION.>
startscript {
do <MakeGrid>
closes all
do <KillAccess(1)>
do <KillAccess(2)>
do <KillAccess(4)>
for <x;6;7> do <KillAccess(%x%)>
do <KillAccess(9)>
do <KillAccess(12)>
do <KillAccess(19)>
for <x;21;22> do <KillAccess(%x%)>
do <KillAccess(24)>
do <KillAccess(26)>
do <KillAccess(29)>
do <KillAccess(36)>
for <x;39;42> do <KillAccess(%x%)>
do <KillAccess(46)>
do <KillAccess(50)>
do <KillAccess(52)>
do <KillAccess(56)>
do <KillAccess(62)>
set <grid[5];10>
}
end define

define synonyms
end define

define room <StartRoom>
script {
set <gridPos;35>
do <makeExits>
goto <gridroom>
}
end define

define room <DoorRoom>
alias <a small, gloomy room.>
look <The room is completely bare and featureless except for a single door to the north.>
south <GridRoom>
script set <gridPos;5>
end define

define room <GridRoom>
alias <a maze of seemingly identical corridors>
script msg <DEBUG: Exit code for this (%gridPos%) room is = %grid[gridPos]%>
command <north> {
set <gridPos;%gridPos%-8>
if ( %gridpos% <> 5 ) then {
do <makeExits>
goto <GridRoom>
}
else goto <doorroom>
}
command <south> {
set <gridPos;%gridPos%+8>
do <makeExits>
goto <GridRoom>
}
command <east> {
set <gridPos;%gridPos%+1>
do <makeExits>
goto <GridRoom>
}
command <west> {
set <gridPos;%gridPos%-1>
do <makeExits>
goto <GridRoom>
}
end define

define room <dummy>
end define

define room <DropRoom>
look <This is the part of the maze underneath the grate where Graham dropped in.>
north <GridRoom>
south <GridRoom>
west <GridRoom>
script set <gridPos; 35>
end define

define room <MonsterRoom>
alias <a maze of seemingly identical corridors>
look <In this area of the maze, it is evident that a creature has roamed through here.>
south <GridRoom>
script set <gridPos; 8>
end define

define room <MonsterRoom2>
alias <a maze of seemingly identical corridors>
look <In this area of the maze, it is evident that a creature has roamed through here.>
south <GridRoom>
script set <gridPos; 49>
end define

define room <MonsterRoom3>
alias <a maze of seemingly identical corridors>
look <In this area of the maze, it is evident that a creature has roamed through here.>
west <GridRoom>
script set <gridPos; 64>
end define

define procedure <MakeGrid>
set numeric <gridPos;0>
for <i;1;8> set numeric <grid[i];1>
for <i;57;64> set numeric <grid[i];4>
for <i;8;64;8> set numeric <grid[i];%grid[i]%+2>
for <i;1;57;8> set numeric <grid[i];%grid[i]%+8>

end define

define procedure <makeExits>
create exit north <GridRoom;dummy>
create exit east <GridRoom;dummy>
create exit south <GridRoom;dummy>
create exit west <GridRoom;dummy>
set numeric <gridVal;%grid[gridPos]%>
if ( %gridVal% > 7 ) then {
create exit west <GridRoom;>
set <gridVal;%gridVal%-8>
}
if ( %gridVal% > 3 ) then {
create exit south <GridRoom;>
set <gridVal;%gridVal%-4>
}
if ( %gridVal% > 1 ) then {
create exit east <GridRoom;>
set <gridVal;%gridVal%-2>
}
if ( %gridVal% > 0 ) then {
create exit north <GridRoom;>
}

end define

define procedure <KillAccess>
set numeric <BlockBox;$parameter(1)$>
set <BlockBox;%BlockBox%+8>
set numeric <ExitsBlocked;%grid[BlockBox]%>
if ( %ExitsBlocked% > 7 ) then set <ExitsBlocked;%ExitsBlocked%-8>
if ( %ExitsBlocked% > 3 ) then set <ExitsBlocked;%ExitsBlocked%-4>
if ( %ExitsBlocked% > 1 ) then set <ExitsBlocked;%ExitsBlocked%-2>
if ( %ExitsBlocked% = 0 ) then set <grid[BlockBox];%grid[BlockBox]%+1>
set <BlockBox;%BlockBox%-16>
if ( %BlockBox% > 8 ) then {
set <ExitsBlocked;%grid[BlockBox]%>
if ( %ExitsBlocked% > 7 ) then set <ExitsBlocked;%ExitsBlocked%-8>
if ( %ExitsBlocked% < 4 ) then set <grid[BlockBox];%grid[BlockBox]%+4>
}
set <BlockBox;%BlockBox%+7>
make sure we aren
set numeric <isLeftCol;0>
for <i;8;64;8> {
if ( %BlockBox% = %i% ) then set <isLeftCol;1>
}
if ( %isLeftCol% <> 1 ) then {
set <ExitsBlocked;%grid[BlockBox]%>
if ( %ExitsBlocked% > 7 ) then set <ExitsBlocked;%ExitsBlocked%-8>
if ( %ExitsBlocked% > 3 ) then set <ExitsBlocked;%ExitsBlocked%-4>
if ( %ExitsBlocked% < 2 ) then set <grid[BlockBox];%grid[BlockBox]%+2>
}
set <BlockBox;%BlockBox%+2>
make sure we aren
set numeric <isRightCol;0>
for <i;1;57;8> {
if ( %BlockBox% = %i% ) then set <isRightCol;1>
}
if ( %isRightCol% <> 1 ) then {
set <ExitsBlocked;%grid[BlockBox]%>
if ( %ExitsBlocked% < 8 ) then set <grid[BlockBox];%grid[BlockBox]%+8>
}

end define

define text <intro>
A demonstration of using one Quest room to represent a grid of locations, in this example a 8 x 8 (64 cell) grid, with lots of the cells inaccessible to form a "maze"
end define

define text <win>
Enter win text here
end define

define text <lose>
Enter lose text here
end define

MaDbRiT
30 Jun 2005, 22:54
Steve wrote,

In your code, when you finally reach the room with the door, you can’t return south back into the maze. So I thought if I put the south exit of the DoorRoom set to “GridRoom”, it would send me back into the maze. After testing it, it seemed to work, however, if you go further into the maze and try to find the DoorRoom again, you’ll get an error 9 and the game shuts down.



You are basically right - you just need to call the 'makeExits' and set the 'gridpos' variable appropriately before moving the player back to the gridroom. The reworked code below shows this.

Further, I wanted to make the room that you start out in different so people roaming through the maze would realize that they’re back to the room that they started in. So in other words, I wanted them to get a description similar to “This seems to be the room that you started from since you can see the open grate above you”. Then of course, there should be an object in the room called “grate” so they can examine it if they chose to.



You can make the gridroom 'APPEAR' to be a different room without actually creating another room (which gets way too complicated!) by simply building a test that adds an appropriate description to the gridroom when you are at grid cell 35 - I've done that in the example below.

You can then put a grate object in the gridroom and have a simple test in the 'makeExits' procedure which either conceals or reveals the grate object depending on whether you are at cell 35 - thus giving the impression of being in a different room. I've done that in the code below too.

Finally, I wanted to make three rooms [8, 49, 64] (labeled as MonsterRoom, MonsterRoom2, and MonsterRoom3)where a creature would randomly appear in. The discussion of this general idea is in another recent thread but my question relates to the one above in reference to the DoorRoom. Whether or not the creature is in the room, I want the player to be able to “notice” that a creature had been in the room so these three rooms would have their own room descriptions similar to “It appears that in this part of the maze, a creature has recently passed through”
When I began trying to create room 8, I received worse results than when I threw in the “GridRoom” exit on the DoorRoom. I couldn’t even get an exit out of room 8.



Once again, you don't need to create any more rooms, you just need to create the IMPRESSION of more rooms. Just as I used a test to add a description to the gridroom when the cell value was 35, you can do exactly the same to add your rooms with evidence of creature passing through by testing the value of gridpos.

I've added this to the code too. In total these changes took maybe 20 or so lines of code to accomplish so it is much easier than messing about moving the player in and out of real and virtual rooms!

Here's the code (watch for the word wrap as usual)

' Grid of locations within one room 

define game <Grid Demo>

asl-version <350>

gametype singleplayer

game version <1.0>
game author <MaDbRiT>
game copyright <© 2005 AGB>
game info <Demo>

start <StartRoom>

startscript {
do <MakeGrid> 'This builds a 8 x 8 grid (with hard boundaries)

' Calling 'KillAccess' procedure with the cell number as a parameter closes all
' (N,S,E & W) entrances to the cell referenced.

do <KillAccess(1)>
do <KillAccess(2)>
do <KillAccess(4)>
for <x;6;7> do <KillAccess(%x%)>
do <KillAccess(9)>
do <KillAccess(12)>
do <KillAccess(19)>
for <x;21;22> do <KillAccess(%x%)>
do <KillAccess(24)>
do <KillAccess(26)>
do <KillAccess(29)>
do <KillAccess(36)>
for <x;39;42> do <KillAccess(%x%)>
do <KillAccess(46)>
do <KillAccess(50)>
do <KillAccess(52)>
do <KillAccess(56)>
do <KillAccess(62)>

'Open additional (special) Exits to north/south in Cell 5

'This is the exit from the gridroom maze

set <grid[5];10>
}


end define

define room <StartRoom>
script {
set <gridPos;35>
do <makeExits>
goto <gridroom>
}
end define

define room <DoorRoom>
alias <a small, gloomy room.>
look <The room is completely bare and featureless except _
for a single door to the north. A corridor leads south...>
south {
set <gridPos;13>
do <makeExits>
goto <gridroom>
}
end define


define room <GridRoom>
script {
' msg <DEBUG: Exit code for this (%gridPos%) room is = %grid[gridPos]%>
}
alias <a maze of seemingly identical corridors>

description {
if ( %gridpos%=35 ) then {
msg <This is the part of the maze underneath the grate where Graham dropped in. |nThere is a |bgrate|xb here.>
}
if ( %gridpos%=8 ) or (%gridpos%=49) or (%gridpos%=64) then {
msg <In this area of the maze, it is evident that a creature has roamed through here.>
}
}

command <north> {
set <gridPos;%gridPos%-8>
if (%gridpos%<>5) then {
do <makeExits>
goto <GridRoom>
}
else goto <doorroom>
}

command <south> {
set <gridPos;%gridPos%+8>
do <makeExits>
goto <GridRoom>
}

command <east> {
set <gridPos;%gridPos%+1>
do <makeExits>
goto <GridRoom>
}

command <west> {
set <gridPos;%gridPos%-1>
do <makeExits>
goto <GridRoom>
}

define object <grate>
look <a large ornamental grate.>
end define

end define

define room <dummy>

end define

define procedure <MakeGrid>
set numeric <gridPos;0>

' ** Set Basic boundaries of 8 x 8 grid

' ** Set exit north OFF for top row of grid
for <i;1;8> {
set numeric <grid[i];1>
}

' ** Set exit south OFF for bottom row of grid
for <i;57;64> {
set numeric <grid[i];4>
}

' ** Set exit east OFF for right row of grid
for <i;8;64;8> {
set numeric <grid[i];%grid[i]%+2>
}

' ** Set exit west OFF for left of grid
for <i;1;57;8> {
set numeric <grid[i];%grid[i]%+8>
}
end define

define procedure <makeExits>
create exit north <GridRoom;dummy>
create exit east <GridRoom;dummy>
create exit south <GridRoom;dummy>
create exit west <GridRoom;dummy>
set numeric <gridVal;%grid[gridPos]%>

if (%gridpos%=35) then reveal <grate>
else conceal <grate>

if (%gridVal% >7) then {
create exit west <GridRoom;>
set <gridVal;%gridVal%-8>
}

if (%gridVal% >3) then {
create exit south <GridRoom;>
set <gridVal;%gridVal%-4>
}

if (%gridVal% >1) then {
create exit east <GridRoom;>
set <gridVal;%gridVal%-2>
}

if (%gridVal% >0) then {
create exit north <GridRoom;>
}
end define

define procedure <KillAccess>
set numeric <BlockBox;$parameter(1)$>

' In this procedure we need to modify the boxes bordering the chosen box
' rather than the box to be blocked itself. First up is to block the
' exit to this box from the south.
' Move down a row.
set <BlockBox;%BlockBox%+8>
set numeric <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8>

' Discard WEST bit
if (%ExitsBlocked% >3) then set <ExitsBlocked;%ExitsBlocked%-4>

' Discard SOUTH bit
if (%ExitsBlocked% >1) then set <ExitsBlocked;%ExitsBlocked%-2>

' Discard EAST bit
if (%ExitsBlocked% =0) then set <grid[BlockBox];%grid[BlockBox]%+1> ' Set NORTH bit if not set

'Now the access from the north.
set <BlockBox;%BlockBox%-16>
' IF Makes sure we're not in the top row, (we can ignore this stage if we are)
if (%BlockBox%>8) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8>

' Discard WEST bit
if (%ExitsBlocked% <4) then set <grid[BlockBox];%grid[BlockBox]%+4> ' Set SOUTH bit if not set
}

'Now the access from the west
set <BlockBox;%BlockBox%+7>

' make sure we aren't in the leftmost columnn
set numeric <isLeftCol;0>
for <i;8;64;8> {
if (%BlockBox%=%i%) then set <isLeftCol;1>
}
if (%isLeftCol%<>1) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% >7) then set <ExitsBlocked;%ExitsBlocked%-8>

' Discard WEST bit
if (%ExitsBlocked% >3) then set <ExitsBlocked;%ExitsBlocked%-4>

' Discard SOUTH bit
if (%ExitsBlocked% <2) then set <grid[BlockBox];%grid[BlockBox]%+2> ' Set EAST bit if not set
}

'Now the access from the east
set <BlockBox;%BlockBox%+2>

' make sure we aren't in the rightmost columnn
set numeric <isRightCol;0>
for <i;1;57;8> {
if (%BlockBox%=%i%) then set <isRightCol;1>
}
if (%isRightCol%<>1) then {
set <ExitsBlocked;%grid[BlockBox]%>
if (%ExitsBlocked% <8) then set <grid[BlockBox];%grid[BlockBox]%+8> ' Set WEST bit if not set
}

end define

define text <intro>
A demonstration of using one Quest room to represent a grid of locations, in this example a 8 x 8 (64 cell) grid, with lots of the cells inaccessible to form a "maze"
end define

define text <win>
Enter win text here
end define

define text <lose>
Enter lose text here
end define


Al (MaDbRiT)

steve the gaming guy
02 Jul 2005, 02:49
Wow...that's amazing! Thanks! I am seeing the light!

I have a quick question (which might lead into a longer discussion :D )

The three "rooms" where the creature will randomly appear in...won't that be a little more difficult to make it appear in one of these three rooms when the rooms are actually the same room but different grid positions?

Based on the NPC movement discussion here, it seems as though it would work quite differently on a grid system. I'm thinking I would change the three rooms to three grid positions picked at random (among 8,49,64). I'm just not sure how to twist all of it together.

MaDbRiT
02 Jul 2005, 08:53
Steve wrote

The three "rooms" where the creature will randomly appear in...won't that be a little more difficult to make it appear in one of these three rooms when the rooms are actually the same room but different grid positions?



A little more difficult possibly, but certainly nothing to cause a major headache. You can't really apply the NPC movement theories for 'real rooms' directly to a 'grid of locations within a room' as implemented thus far.

Given you want the creature to appear randomly, in specified locations it is actually a pretty easy 'tweak' of whatever random method you are choosing to position your creature.

Just as with the 'grate' it exists in the gridroom all of the time, but is only made visible when the player is at grid location 35, you can do exactly the same with your monster - create it as hidden in the grid room, then make it visible as a result of your random test.

Try something like this, define you monster inside the gridroom with:

   define object <monster>
look <it looks very hungry, and you are snack-sized!>
end define


Then add the following code to the makeExits procedure

   hide <monster>   
if (%gridpos%=8) or (%gridpos%=64) or (%gridpos%=49) then {
set numeric <monsterhere;$rand(1;3)$>
if (%monsterhere%=3) then show <monster>
}



and to tidy up the gridroom description, replace the current 'description' code with:

  description { 
if ( %gridpos%=35 ) then {
msg <This is the part of the maze underneath the grate where Graham dropped in. |nThere is a |bgrate|xb here.>
}
if ( %gridpos%=8 ) or (%gridpos%=49) or (%gridpos%=64) and not here <monster> then {
msg <In this area of the maze, it is evident that a creature has roamed through here.>
}
if here <monster> then msg <|nI don't wish to alarm you, but there is a |bmonster|xb here!>
}


You might want to swop the reveal/conceal instructions for the GRATE object to be hide/show too - an oversight by me.

Al (MaDbRiT)

steve the gaming guy
11 Jul 2005, 19:56
ooooh, I ran into a problem while testing. Although it is quite convenient to use the map in the lower right corner, there are some players who prefer to type in the commands. If you type nsw or e it sends you to the dummy room and you’re done. If you type it out (north, south, etc), it moves you correctly. I did a quick fix by making synonyms (n=north, etc). That actually fixed that problem.
The second and more important problem, if you type out your commands, although the map shows the correct exits available, the player can still walk through walls. For instance, when you start on grid 35, there is no doorway east. But when you type “east”, you appear in grid 0. If you try this in several different parts of the maze, you eventually get a code 9 error and it shuts the game down.

MaDbRiT
11 Jul 2005, 22:43
Hi Steve

ooooh, I ran into a problem while testing. Although it is quite convenient to use the map in the lower right corner, there are some players who prefer to type in the commands. If you type nsw or e it sends you to the dummy room and you’re done. If you type it out (north, south, etc), it moves you correctly. I did a quick fix by making synonyms (n=north, etc). That actually fixed that problem



Yeah I was aware that you'd need to code synonyms for all the alternative commands N =north etc. you always have to do all the possibilities when you override a quest command - I should have mentioned I hadn't bothered to do it in my demo I suppose!

if you type out your commands, although the map shows the correct exits available, the player can still walk through walls. For instance, when you start on grid 35, there is no doorway east. But when you type “east”, you appear in grid 0. If you try this in several different parts of the maze, you eventually get a code 9 error and it shuts the game down.



That sounds slightly wierd, a bug if ever I saw one! As my copy of the code is at work and I am at home I can't check this out right now. If I get a chance I'll dig it out and see why it happens tomorrow.

Al (MaDbRiT)

MaDbRiT
11 Jul 2005, 23:16
Steve

Ahem! :oops: Just came to me that this is a simple oversight on my part, I've coded directional commands for north etc, and while the create/destroy exit routines I've done disable directions on the compass rose (navigation buttons) they don't affect execution of typed user commands (which override conventional things like needing exits!)

Easy to fix though, just need to check that the exit chosen exists before letting the player pass through it... swopping the exits code for something like this should do it;



command <north> {
if ($instr(#quest.doorways.dirs#,north)$<>) then {
set <gridPos;%gridPos%-8>
if (%gridpos%<>5) then {
do <makeExits>
goto <GridRoom>
}
else goto <doorroom>
}
else msg <You can't go there.>
}

command <south> {
if ($instr(#quest.doorways.dirs#,south)$<>) then {
set <gridPos;%gridPos%+8>
do <makeExits>
goto <GridRoom>
}
else msg <You can't go there.>
}

command <east> {
if ($instr(#quest.doorways.dirs#,east)$<>) then {
set <gridPos;%gridPos%+1>
do <makeExits>
goto <GridRoom>
}
else msg <You can't go there.>
}

command <west> {
if ($instr(#quest.doorways.dirs#,west)$<>) then {
set <gridPos;%gridPos%-1>
do <makeExits>
goto <GridRoom>
}
else msg <You can't go there.>
}


With the synonyms in place, this should cater for player navigation by compass rose buttons or typed commands

Al (MaDbRiT)

steve the gaming guy
12 Jul 2005, 01:55
You are quick with the responses! Thank you! I'll work on this tomorrow. :P

EDIT:
Hmmmm, ok. Now I've changed it and when you start the game, it shows the available exits but if you try to take any exits (even the non-exits), it says you can't go there.

MaDbRiT
12 Jul 2005, 20:43
Steve wrote

Now I've changed it and when you start the game, it shows the available exits but if you try to take any exits (even the non-exits), it says you can't go there.



That's what comes of typing 'untried' stuff when you are tired. You b####r it up :oops:

I made a syntax error (substituted a comma for a semi-colon) and completely 'lost' the test condition ( <>0 ) - it SHOULD have looked like this...

   command <north> { 
if ($instr(#quest.doorways.dirs#;north)$<>0) then {
set <gridPos;%gridPos%-8>
if (%gridpos%<>5) then {
do <makeExits>
goto <GridRoom>
}
else goto <doorroom>
}
else msg <You can't go there.>
}

command <south> {
if ($instr(#quest.doorways.dirs#;south)$<>0) then {
set <gridPos;%gridPos%+8>
do <makeExits>
goto <GridRoom>
}
else msg <You can't go there.>
}

command <east> {
if ($instr(#quest.doorways.dirs#;east)$<>0) then {
set <gridPos;%gridPos%+1>
do <makeExits>
goto <GridRoom>
}
else msg <You can't go there.>
}

command <west> {
if ($instr(#quest.doorways.dirs#;west)$<>0) then {
set <gridPos;%gridPos%-1>
do <makeExits>
goto <GridRoom>
}
else msg <You can't go there.>
}


Now that DOES work, 'cause I've actually tested it this time - :lol:

Al (MaDbRiT)

steve the gaming guy
13 Jul 2005, 18:34
haha...ok thanks! I'll work on it some time today.