Jump to content
IGNORED

New XB Game: Wizard's Doom (In Progress)


adamantyr

Recommended Posts

My next game! It is a spiritual and intentional sequel to the Wizard's Lair/Wizard's Revenge games from Rainbow Software, so that it will stand as a trilogy!

 

Particulars:

- Extended BASIC with 32k RAM (An upgrade from the prior games, which had to fit in 16k)

- Choose between a warrior or magic-user at the start of the game for different starting equipment and statistics

- A map that's actually useful ;)

- A twist on the original "kill the Evil Wizard" in that you have to do something first...

 

Currently I'm working on dungeon movement/creation prototypes to maximize performance and make a good looking maze. I'm debating off-loading data to disk as well for maximum performance. It would be VERY cool to have monsters be much bigger than 16x16 pixels! We will see...

 

Here is the background I've written up:

 

"Many decades of peace have passed since the realm was tormented by the Evil Wizard... He was slain first in the dungeons of first Weymoor Castle, and then in Bleylock Castle's dungeons by brave and mighty heroes. All the good folk of the realm prayed and hoped that he was gone forever...

Alas, it was not to be, as the people of Galdorend have discovered to their horror and grief.

The Evil Wizard has appeared again, by means sinister and unknown. Rumors now whisper that he cannot be killed, for he has achieved some terrible mastery over life and death in his travels in the forbidden zone beyond the threshold of life. He has now claimed the dungeons of Galdorend Castle to fulfill his malevolent designs and wreck vengeance upon the lands and people.

Since his return, many great warriors and skilled magic-users have entered the dungeons, seeking to kill the Evil Wizard once and for all and lay claim to the vast store of treasure he possesses. None have ever returned to the light of day. Strange fell creatures have been seen abroad at night, emerging from the dungeon depths to plague the innocent and bring valuables back to the Wizard.

The townspeople of Galdorend have offered a great reward to be rid of the Wizard, but such wealth is nothing compared to what the Wizard has... and this time, it is not enough to just slay the Wizard. His source of unending life must be found and destroyed first, lest he rise again.

You are the latest in a line of hopeful heroes who have sought out the dungeon's dark malodorous entrance, with only a few simple weapons and spells at hand to fight the forces of evil. As you enter the darkness the doors slowly swing shut behind you... an evil cackle arises from the depths as you grimly move forward to make your destiny..."

  • Like 7
Link to comment
Share on other sites

A regular disk drive should be fine, my main thought was to offload monster graphics and monster stats (which are only needed during combat) so keep room open for the engine.

 

I'm definitely aiming for a larger scale game than the first two... interestingly, Wizard's Revenge is actually smaller in size and has less monster variety than Wizard's Lair.

 

I'm also doing my mazes a little differently to make them larger, the first level will be around 6x6 or 34 chambers, and the fifth level (my present estimated last level) will be 10x10 or 90 chambers in size.

 

post-17978-0-98172800-1465335548_thumb.png

Currently I just got some baseline graphics for dungeon rendering, I plan to do some artistic work here and make it more interesting.

 

post-17978-0-16646500-1465335553_thumb.png

  • Like 4
Link to comment
Share on other sites

Just to share, here is my prototype maze program. It does the following:

 

- Generates a maze of the appropriate size

- Renders the 3D view

- Allows you to move around the maze

- Shows a small-scale map of the dungeon

 

Key commands are:

F - Forward

L- Turn Left

R - Turn Right

B - Move backwards

M - View Map

 

If you want to generate a larger maze, change the LV value on line 100 to 2-6. Don't make it bigger than six unless you want to change the size of the MZ$ array. :)

10 OPTION BASE 1 :: DIM MZ$(10,10),YX(4,2),VW(3,5),DR(4,5),D$(4)
20 RESTORE 13000 :: FOR I=1 TO 4 :: READ YX(I,1),YX(I,2) :: NEXT I
30 FOR I=1 TO 4 :: FOR J=1 TO 5 :: READ DR(I,J) :: NEXT J :: NEXT I :: FOR I=1 TO 4 :: READ D$(I) :: NEXT I
40 P1$=CHR$(136)&CHR$(137) :: P2$=CHR$(137)&CHR$(136) :: R1$=RPT$(P1$,7) :: R2$=RPT$(P2$,7)
100 O=1 :: LV=1 :: DISPLAY AT(5,9)ERASE ALL:"WIZARD'S DOOM"
110 GOSUB 4000 :: GOSUB 5030 :: PR=ASC(SEG$(R$,1,1)) :: PC=ASC(SEG$(C$,1,1)) :: PC=C :: DISPLAY AT(24,:"PRESS ANY KEY"
120 CALL KEY(0,K,S) :: IF S=0 THEN 120 ELSE CALL CLEAR
130 GOSUB 3000 :: GOSUB 3500 :: GOSUB 3600
140 CT=0 :: GOSUB 2000 :: GOTO 130
2000 K$="" :: DISPLAY AT(23,1)SIZE(13):"ACTION?:"
2010 CALL KEY(0,K,S) :: CT=CT+1 :: IF CT>35 THEN CT=0
2020 IF K=65 THEN 2010 ELSE IF S=0 THEN 2010
2030 CALL SOUND(30,600,5,480,5) :: IF K<65 THEN 2040 ELSE K$=K$&CHR$(K) :: DISPLAY AT(23,9)SIZE(3):K$ :: GOTO 2010
2040 IF K<>13 THEN 2010
2050 A=POS("LRFBM",SEG$(K$,1,1),1) :: IF A=0 THEN 2000 ELSE ON A GOTO 2060,2070,2080,2090,2110
2060 O=O-1 :: IF O=0 THEN O=4 :: RETURN ELSE RETURN
2070 O=O+1 :: IF O=5 THEN O=1 :: RETURN ELSE RETURN
2080 D=O :: GOTO 2100
2090 D=O+2 :: IF D>4 THEN D=D-4
2100 IF VW(1,A)=0 THEN 2000 ELSE PR=PR+YX(D,1) :: PC=PC+YX(D,2) :: RETURN
2110 GOSUB 5000 :: RETURN
2120 GOSUB 5000 :: RETURN
3000 VR=PR :: VC=PC :: FOR I=1 TO 3 :: FOR J=1 TO 5 :: VW(I,J)=0 :: NEXT J :: NEXT I
3010 FOR L=1 TO 3 :: CH=ASC(SEG$(MZ$(VR,VC),1,1)) :: FOR I=1 TO 5 :: IF CH AND DR(O,I)THEN VW(L,I)=1 ELSE VW(L,I)=0
3020 NEXT I :: VR=VR+YX(O,1) :: VC=VC+YX(O,2) :: IF VR<1 OR VR>LV+4 OR VC<1 OR VC>LV+4 THEN RETURN
3030 NEXT L :: RETURN
3500 FOR I=1 TO 22 :: CALL HCHAR(I,3,133,22) :: NEXT I :: K=1
3510 DW=1+(K-1)*2+VW(K,1) :: GOSUB 8000 :: DW=1+(K-1)*2+VW(K,2) :: GOSUB 8100 :: DW=VW(K,5)*K :: IF DW>0 THEN GOSUB 8300
3520 DW=ABS(VW(K,3)=0)*K :: IF DW>0 THEN GOSUB 8200 :: RETURN
3530 K=K+1 :: IF K<4 THEN 3510 ELSE RETURN
3600 DISPLAY AT(1,24)$(O) :: DISPLAY AT(3,24):STR$(ER)&","&STR$(EC) :: RETURN
4000 A=1 :: B=INT((LV+4)^2*0.9) :: N,D=0 :: R=INT(RND*(4+LV))+1 :: C=INT(RND*(4+LV))+1
4005 FOR I=1 TO LV+4 :: FOR J=1 TO LV+4 :: MZ$(I,J)=CHR$(0) :: NEXT J :: NEXT I :: R$=CHR$(R) :: C$=CHR$(C)
4010 TR=R+YX(D+1,1) :: TC=C+YX(D+1,2) :: IF TR<1 OR TR>LV+4 OR TC<1 OR TC>LV+4 THEN 4090
4020 IF MZ$(TR,TC)=CHR$(0)THEN V=1 :: GOTO 4025 ELSE 4090
4025 I=ASC(MZ$(R,C)) :: J=ASC(MZ$(TR,TC)) :: ON D+1 GOTO 4030,4040,4050,4060
4030 I=I OR 1 :: J=J OR 4 :: GOTO 4070
4040 I=I OR 2 :: J=J OR 8 :: GOTO 4070
4050 I=I OR 4 :: J=J OR 1 :: GOTO 4070
4060 I=I OR 8 :: J=J OR 2
4070 MZ$(R,C)=CHR$(I) :: MZ$(TR,TC)=CHR$(J) :: N=0 :: R=TR :: C=TC :: R$=R$&CHR$(R) :: C$=C$&CHR$(C) :: A=A+V :: IF A>=B THEN 4110
4080 RANDOMIZE :: CALL PEEK(-31808,D) :: D=D AND 3 :: GOTO 4010
4090 N=N+1 :: IF N=2 THEN 4100 ELSE D=D+1 :: D=D AND 3 :: GOTO 4010
4100 N=0 :: J=INT(RND*LEN(R$))+1 :: R=ASC(SEG$(R$,J,1)) :: C=ASC(SEG$(C$,J,1)) :: D=0 :: GOTO 4010
4110 R=ASC(SEG$(R$,A,1)) :: C=ASC(SEG$(C$,A,1)) :: I=ASC(MZ$(R,C)) :: I=I OR 16 :: MZ$(R,C)=CHR$(I)
4120 RETURN
5000 CALL CLEAR :: RESTORE 10000 :: CALL COLOR(13,2,16,14,2,16) :: FOR I=1 TO 4 :: READ A$ :: CALL CHAR(124+I*4,A$) :: NEXT I
5010 FOR I=1 TO LV+4 :: FOR J=1 TO LV+4 :: C=ASC(MZ$(I,J)) :: C=C AND 15 :: CALL VCHAR(I+7,J+11,128+C) :: NEXT J :: NEXT I :: DISPLAY AT(24,:"PRESS ANY KEY"
5020 CALL KEY(0,K,S) :: IF S=0 THEN 5020 ELSE CALL CLEAR
5030 RESTORE 11000 :: CALL COLOR(13,5,2,14,5,6) :: FOR I=1 TO 4 :: READ A$ :: CALL CHAR(124+I*4,A$) :: NEXT I :: RETURN
8000 ON DW GOTO 8005,8010,8015,8020,8025,8030
8005 M=1 :: N=4 :: GOSUB 8400 :: RETURN
8010 FOR I=1 TO 18 STEP 2 :: DISPLAY AT(2+I,1):P1$; :: DISPLAY AT(3+I,1):P2$; :: NEXT I :: M=3 :: N=4 :: GOSUB 8400 :: RETURN
8015 M=5 :: N=8 :: GOSUB 8400 :: RETURN
8020 M=5 :: N=6 :: GOSUB 8400 :: CALL VCHAR(8,9,138, :: CALL VCHAR(8,10,129) :: CALL VCHAR(9,10,140,6) :: CALL VCHAR(15,10,131) :: RETURN
8025 M=9 :: N=10 :: GOSUB 8400 :: RETURN
8030 CALL VCHAR(9,11,129) :: CALL VCHAR(10,11,132,4) :: CALL VCHAR(14,11,131) :: CALL VCHAR(11,12,139,2) :: RETURN
8100 ON DW GOTO 8105,8110,8115,8120,8125,8130
8105 M=1 :: N=4 :: GOSUB 8410 :: RETURN
8110 FOR I=1 TO 18 STEP 2 :: DISPLAY AT(2+I,21):P1$; :: DISPLAY AT(3+I,21):P2$; :: NEXT I :: M=3 :: N=4 :: GOSUB 8410 :: RETURN
8115 M=5 :: N=8 :: GOSUB 8410 :: RETURN
8120 M=5 :: N=6 :: GOSUB 8410 :: CALL VCHAR(8,18,138, :: CALL VCHAR(8,17,128) :: CALL VCHAR(9,17,141,6) :: CALL VCHAR(15,17,130) :: RETURN
8125 M=9 :: N=10 :: GOSUB 8410 :: RETURN
8130 CALL VCHAR(9,16,128) :: CALL VCHAR(10,16,132,4) :: CALL VCHAR(14,16,130) :: CALL VCHAR(11,15,139,2) :: RETURN
8200 ON DW GOTO 8210,8220,8230
8210 FOR I=1 TO 14 STEP 2 :: DISPLAY AT(4+I,5):R1$; :: DISPLAY AT(5+I,5):R2$; :: NEXT I :: RETURN
8220 FOR I=1 TO 6 :: CALL HCHAR(8+I,11,138,6) :: NEXT I :: RETURN
8230 CALL HCHAR(11,13,139,2) :: CALL HCHAR(12,13,139,2) :: RETURN
8300 ON DW GOTO 8310,8320,8330
8310 DISPLAY AT(21,10):CHR$(128)&CHR$(141)&CHR$(140)&CHR$(129); :: RETURN
8320 DISPLAY AT(16,11):CHR$(134)&CHR$(135); :: RETURN
8330 RETURN
8400 FOR I=M TO N :: C=132-(I=N)*8 :: CALL VCHAR(I,2+I,129) :: CALL VCHAR(I+1,2+I,C,22-I*2) :: CALL VCHAR(23-I,2+I,131) :: NEXT I :: RETURN
8410 FOR I=M TO N :: C=132-(I=N)*9 :: CALL VCHAR(I,25-I,128) :: CALL VCHAR(I+1,25-I,C,22-I*2) :: CALL VCHAR(23-I,25-I,130) :: NEXT I :: RETURN
10000 DATA FFFFFFFFFFFFFFFFC3C3C3C3C3C3FFFFFFFFC0C0C0C0FFFFC3C3C0C0C0C0FFFF
10010 DATA FFFFC3C3C3C3C3C3C3C3C3C3C3C3C3C3FFFFC0C0C0C0C3C3C3C3C0C0C0C0C3C3
10020 DATA FFFF03030303FFFFC3C303030303FFFFFFFF00000000FFFFC3C300000000FFFF
10030 DATA FFFF03030303C3C3C3C303030303C3C3FFFF00000000C3C3C3C300000000C3C3
11000 DATA 0103070F1F3F7FFF80C0E0F0F8FCFEFFFF7F3F1F0F070301FFFEFCF8F0E0C080
11010 DATA FFFFFFFFFFFFFFFF000000000000000000070A1D3A7D000000E0B058BC5E0000
11020 DATA 40BFFFFFABD5AA7F02FDD2FEFE7EAEFD01FEFAAE10EFAFEAFF1177DDFF44DD77
11030 DATA FEFEFEFEFEFEFEFE7F7F7F7F7F7F7F7F00000000000000000000000000000000
13000 DATA -1,0,0,1,1,0,0,-1
13010 DATA 8,2,1,4,16
13020 DATA 1,4,2,8,16
13030 DATA 2,8,4,1,16
13040 DATA 4,1,8,2,16
13050 DATA NORTH,EAST,SOUTH,WEST
Edited by adamantyr
  • Like 2
Link to comment
Share on other sites

I find my best tools are just a simple text editor and Super Extended BASIC to do targeted re-sequencing as needed work best for me. :)

 

We all have our preferences of course. However, I personally find the ability of using descriptive labels and no line numbers, along with proper indentation a god send in XB programming. Just ask Owen :) If you have never tried it, I suggest you give it a shot just to make sure you're not missing out on a great tool :grin:

  • Like 2
Link to comment
Share on other sites

Thank you! I actually used that image as a baseline and did some extrapolation... obviously it's very hard to do a sinister face in such a tight pixel area. :P

 

I'll add some stars and other stuff to his robe as well, this was just the initial version. I'm planning to use up to eight sprites for monsters, and load graphics data from disk each time.

 

I would actually love to know WHERE the Wizard image came from... there's a signature clearly visible on the manuals in the lower left corner but it's nearly unreadable. I assumed it was some public domain image, but it's possible it was an original piece of work. In truth, who worked AT Rainbow software is entirely conjecture. They only appear to have released the two games that I can see, and then disappeared. Anyone have any intel on this?

  • Like 1
Link to comment
Share on other sites

Spent this weekend mining out the formulas and statistics of the first two games...

Gameplay is rather simple but effective, both games have the same pattern. There are no attack rolls, just damage. Monsters have only a single stat, power. They damage not just your constitution/health but your attributes as well on every attack. Floating point math is used to mask this; TI BASIC internal manipulation of floats to integers is rather impressive with this. Every attack checks if you are low enough on ability scores that you lose your weapon.

Treasure points and experience are pointless other than impacting your final rating.

Magic spells are all pretty straight forward, but several have unique code for more fun. A Medusa item in WR let's you turn monsters to stone. (And I think if you leave and come back they are still there!) And a carpet will whisk you to the next level immediately. (I think it crashes the game on level 5 though, or results in an automatic failure).

Dungeons have random corridors plotted out on a square grid, a maximum of 8x8 in size. Treasure, items and monsters are all deterministic; each item has a count to place and what level range they exist at.

Wizard's Revenge is smaller in scale while having richer gameplay with individual monster graphics and better dungeon walls. Mazes are only 6x6 in size maximum, there are less weapons and monsters, and game play is notably easier, despite not starting with any equipment. Since both games are copyrighted 1986, my guess is that they were developed one after the other. The code listing actually supports this; the same functions appear close to the same lines, it's like someone took WL's code and rewrote it in place.

Codewise, both games are fairly well written. The use of DATA statements with RESTORE is done well to read in data as its needed. The fact they had to squeeze the game into 16k and for cassette means they didn't have a lot of room for variety. They weren't aware of more advanced XB techniques such as bitwise operations, but those were fairly unknown in 1986 among the 99'er community. (Millers Graphics were just awesome!) My only beef is, don't use ampersand or underscore as variable names! Sheesh...

 

I love the manuals. Besides the incredible cover artwork (again, who made it?!), they are printed very well. I definitely want to re-create a manual for my game that is a match for them!

 

Why Rainbow Software wrote two games and then disappeared is anyone's guess... Mine is that it was a small group, maybe 1-3 people, who owned a TI console with only a cassette player. They wrote their games and spent QUITE a bit on getting labels and manuals created. Seriously the cassettes had metallic silver labels with blue/red lettering! When I bought WR the disk re-used a cassette label, which tells me they didn't separate the two. Anyway, I suspect that sales were not as strong as they hoped (Which in the TI market place is not a surprise) and they closed the company down afterwards.

 

I'm currently plotting out my own mechanics for the 3rd game. Since I'm offloading a lot of data to disk and I have more memory to work with, I definitely want a game that has a greater degree of sophistication. Something closer to Dungeons of Daggorath on the TRS-80 Color Computer.

Edited by adamantyr
Link to comment
Share on other sites

Work continues... :) I spent last night drawing up several monsters. I'm holding off sharing so people can experience them first hand in game!

 

I'm also venturing into some new territory... assembly routine help. Documentation on it is rather sparse; the editor/assembler manual and Molesworth's book are the only two I've found that have much detail.

 

My plan is to move the 3D drawing routines and monster/sprite management into low memory functions. This will let me instantly refresh the view and handle multiple sprites much more efficiently.

 

I've figured out how to implement what I need without the NUMREF utility, which is largely wasted... I am curious though how past 99'ers managed to do the sneaky trick of embedding the object code in an Extended BASIC loader program and uploading it to low memory from there, instead of having it be explicitly loaded with CALL LOAD... anyone have any insight?

Edited by adamantyr
  • Like 1
Link to comment
Share on other sites

I am curious though how past 99'ers managed to do the sneaky trick of embedding the object code in an Extended BASIC loader program and uploading it to low memory from there, instead of having it be explicitly loaded with CALL LOAD... anyone have any insight?

http://atariage.com/forums/topic/177366-bitmap-image-conversions/page-2?do=findComment&comment=2214052

 

This information was hard to come by, so it's worth documenting again. Extended BASIC builds a program starting at the top of memory. There are two pointers it uses during this, one points to the start of the line number table, the other to the end of the line number table.

 

When a new line is added, the line number table is shifted downwards in memory (this is why a large program starts to slow down when you add new lines). It puts the line building downwards from the start of the line number table pointer, then updates both pointers to the new table.

 

However, when Extended BASIC saves program code, it saves till the top of RAM no matter what the pointers say. Of course all this is only true for code in the 32k RAM.

 

This trick takes advantage of this behaviour by pushing the start and end points of the line number table lower in RAM. The program will then build downwards from that point, and SAVE and OLD will preserve all data right to the top automatically.

 

So first you have to start with NEW, because there must be no data in memory (otherwise updating the pointers without moving it will lose the program). The pointers are at >8330 and >8332 - just set them to just below the new top of memory -- although 1 byte lower is sufficient it's better to keep things aligned on even bytes, so I use two bytes lower. You can use CALL INIT/CALL LOAD to set these pointers, but in Classic99 I just use the debugger.

 

For this program, I set a value of >C9E4. This gives me 6k for the pattern table at >C9E6, 6k for the color table at >E1E6, 1k for saving VDP data at >F9E6, and 512 bytes for the program itself at >FDE6.

 

Next, enter the program. You can MERGE it, type it, or with Classic99 I just paste it in from Notepad.

 

To get the assembly into place, just CALL INIT::CALL LOAD("DSK1.ASM/O"). Because the assembly program is AORG'd, it loads into the correct place. Naturally you are responsible for making sure that space is free!

 

SAVE DSK1.PROGRAM -- and now you have an Extended BASIC program with space for almost 14k of data at the top, all loading in one fast loader with the assembly language in place.

Edited by sometimes99er
  • Like 1
Link to comment
Share on other sites

Got my assembly video routines in place! Now the dungeon 3D view draws very fast, basically instantly!

 

The only downside is that there is still a noticable lag caused by Extended BASIC code calculating out open/closed viewport data (whether to draw a wall or passage, etc). I think I can live with it, it's all about timing. I originally wasn't going to have it black out the view port first, but testing has shown it create a sense of lag, if not actual, when the screen does nothing for what seems over a second before abruptly changing.

Edited by adamantyr
  • Like 1
Link to comment
Share on other sites

So I ended up making two versions of the dungeon drawing... one with a buffer and one that just draws directly to screen.

 

Interestingly, the buffered one was the worse of the two. Sure it updated the screen instantly, but the second or two of lag (mostly from the calculations in Extended BASIC) created a disjointed feeling. I think partly because without the sense of the view being built, you didn't feel like you were MOVING.

 

My second version just draws directly to the screen for each section. The result is MUCH more pleasing because it just feels like a charged up version of the original, and you see stuff happening. I think I'll be using that one. :)

  • Like 2
Link to comment
Share on other sites

 

 

10 OPTION BASE 1 :: DIM MZ$(10,10),YX(4,2),VW(3,4),DR(4,4),D$(4)
20 RESTORE 13000 :: FOR I=1 TO 4 :: READ YX(I,1),YX(I,2):: NEXT I 
30 FOR I=1 TO 4 :: FOR J=1 TO 4 :: READ DR(I,J):: NEXT J :: NEXT I :: FOR I=1 TO 4 :: READ D$(I):: NEXT I
100 O=1 :: LV=1 :: DISPLAY AT(5,9)ERASE ALL:"WIZARD'S DOOM"
110 GOSUB 4000 :: GOSUB 5030 :: PR=ASC(SEG$(R$,1,1)):: PC=ASC(SEG$(C$,1,1)):: DISPLAY AT(24,:"PRESS ANY KEY"
120 CALL KEY(0,K,S):: IF S=0 THEN 120 ELSE CALL CLEAR
130 GOSUB 3000 :: GOSUB 3500 :: GOSUB 3600
140 CT=0 :: GOSUB 2000 :: GOTO 130

2000 K$="" :: DISPLAY AT(23,1)SIZE(13):"ACTION?:"
2010 CALL KEY(0,K,S):: CT=CT+1 :: IF CT>35 THEN CT=0
2020 IF K=65 THEN 2010 ELSE IF S=0 THEN 2010
2030 CALL SOUND(30,600,5,480,5) :: IF K<65 THEN 2040 ELSE K$=K$&CHR$(K) :: DISPLAY AT(23,9)SIZE(3):K$ :: GOTO 2010
2040 IF K<>13 THEN 2010
2050 A=POS("LRFBM",SEG$(K$,1,1),1):: IF A=0 THEN 2000 ELSE ON A GOTO 2060,2070,2080,2090,2110
2060 O=O-1 :: IF O=0 THEN O=4 :: RETURN ELSE RETURN
2070 O=O+1 :: IF O=5 THEN O=1 :: RETURN ELSE RETURN
2080 D=O :: GOTO 2100
2090 D=O+2 :: IF D>4 THEN D=D-4
2100 IF VW(1,A)=0 THEN 2000 ELSE PR=PR+YX(D,1):: PC=PC+YX(D,2):: RETURN
2110 GOSUB 5000 :: RETURN

3000 VR=PR :: VC=PC :: FOR I=1 TO 3 :: FOR J=1 TO 4 :: VW(I,J)=0 :: NEXT J :: NEXT I
3010 FOR L=1 TO 3 :: CH=ASC(SEG$(MZ$(VR,VC),1,1)):: FOR I=1 TO 4 :: IF CH AND DR(O,I) THEN VW(L,I)=1 ELSE VW(L,I)=0
3020 NEXT I :: VR=VR+YX(O,1):: VC=VC+YX(O,2):: IF VR<1 OR VR>LV+4 OR VC<1 OR VC>LV+4 THEN RETURN
3030 NEXT L :: RETURN

3500 FOR I=1 TO 22 :: CALL HCHAR(I,3,133,22):: NEXT I :: K=1
3510 DW=1+(K-1)*2+VW(K,1):: GOSUB 8000 :: DW=1+(K-1)*2+VW(K,2):: GOSUB 8100 :: DW=ABS(VW(K,3)=0)*K :: IF DW>0 THEN GOSUB 8200 :: RETURN
3520 K=K+1 :: IF K<4 THEN 3510 ELSE RETURN

3600 DISPLAY AT(1,24)$(O):: RETURN

4000 A=1 :: B=INT((LV+4)^2*0.9):: N,D=0 :: R=INT(RND*(4+LV))+1 :: C=INT(RND*(4+LV))+1
4005 FOR I=1 TO LV+4 :: FOR J=1 TO LV+4 :: MZ$(I,J)=CHR$(0):: NEXT J :: NEXT I :: R$=CHR$(R) :: C$=CHR$(C)
4010 TR=R+YX(D+1,1):: TC=C+YX(D+1,2):: IF TR<1 OR TR>LV+4 OR TC<1 OR TC>LV+4 THEN 4090
4020 IF MZ$(TR,TC)=CHR$(0) THEN V=1 :: GOTO 4025 ELSE 4090
4025 I=ASC(MZ$(R,C)):: J=ASC(MZ$(TR,TC)):: ON D+1 GOTO 4030,4040,4050,4060
4030 I=I OR 1 :: J=J OR 4 :: GOTO 4070
4040 I=I OR 2 :: J=J OR 8 :: GOTO 4070
4050 I=I OR 4 :: J=J OR 1 :: GOTO 4070
4060 I=I OR 8 :: J=J OR 2
4070 MZ$(R,C)=CHR$(I):: MZ$(TR,TC)=CHR$(J):: N=0 :: R=TR :: C=TC :: R$=R$&CHR$(R):: C$=C$&CHR$(C):: A=A+V :: IF A>=B THEN RETURN
4080 RANDOMIZE :: CALL PEEK(-31808,D):: D=D AND 3 :: GOTO 4010
4090 N=N+1 :: IF N=2 THEN 4100 ELSE D=D+1 :: D=D AND 3 :: GOTO 4010
4100 N=0 :: J=INT(RND*LEN(R$))+1 :: R=ASC(SEG$(R$,J,1)):: C=ASC(SEG$(C$,J,1)):: D=0 ::  GOTO 4010

5000 CALL CLEAR :: RESTORE 10000 :: CALL COLOR(13,2,16,14,2,16):: FOR I=1 TO 4 :: READ C$ :: CALL CHAR(124+I*4,C$):: NEXT I
5010 FOR I=1 TO LV+4 :: FOR J=1 TO LV+4 :: CALL VCHAR(I+7,J+11,128+ASC(MZ$(I,J))):: NEXT J :: NEXT I :: DISPLAY AT(24,:"PRESS ANY KEY"
5020 CALL KEY(0,K,S):: IF S=0 THEN 5020 ELSE CALL CLEAR
5030 RESTORE 11000 :: CALL COLOR(13,7,2,14,7,11):: FOR I=1 TO 4 :: READ C$ :: CALL CHAR(124+I*4,C$):: NEXT I :: RETURN

8000 ON DW GOTO 8005,8010,8015,8020,8025,8030
8005 M=1 :: N=4 :: GOSUB 8400 :: RETURN
8010 CALL VCHAR(3,3,136,18):: CALL VCHAR(3,4,136,18):: M=3 :: N=4 :: GOSUB 8400 :: RETURN
8015 M=5 :: N=8 :: GOSUB 8400 :: RETURN
8020 M=5 :: N=6 :: GOSUB 8400 :: CALL VCHAR(8,9,137,:: CALL VCHAR(8,10,129):: CALL VCHAR(9,10,132,6):: CALL VCHAR(15,10,131):: RETURN
8025 M=9 :: N=10 :: GOSUB 8400 :: RETURN
8030 CALL VCHAR(9,11,129):: CALL VCHAR(10,11,132,4):: CALL VCHAR(14,11,131):: CALL VCHAR(11,12,139,2):: RETURN

8100 ON DW GOTO 8105,8110,8115,8120,8125,8130
8105 M=1 :: N=4 :: GOSUB 8410 :: RETURN
8110 CALL VCHAR(3,23,136,18):: CALL VCHAR(3,24,136,18):: M=3 :: N=4 :: GOSUB 8410 :: RETURN
8115 M=5 :: N=8 :: GOSUB 8410 :: RETURN
8120 M=5 :: N=6 :: GOSUB 8410 :: CALL VCHAR(8,18,137,:: CALL VCHAR(8,17,128):: CALL VCHAR(9,17,132,6):: CALL VCHAR(15,17,130):: RETURN
8125 M=9 :: N=10 :: GOSUB 8410 :: RETURN
8130 CALL VCHAR(9,16,128):: CALL VCHAR(10,16,132,4):: CALL VCHAR(14,16,130):: CALL VCHAR(11,15,138,2):: RETURN

8200 ON DW GOTO 8210,8220,8230
8210 FOR I=1 TO 14 :: CALL HCHAR(4+I,7,132,14):: NEXT I :: RETURN
8220 FOR I=1 TO 6 :: CALL HCHAR(8+I,11,132,6):: NEXT I :: RETURN
8230 CALL HCHAR(11,13,132,2):: CALL HCHAR(12,13,132,2):: RETURN

8400 FOR I=M TO N :: CALL VCHAR(I,2+I,129):: CALL VCHAR(I+1,2+I,132,22-I*2):: CALL VCHAR(23-I,2+I,131):: NEXT I :: RETURN
8410 FOR I=M TO N :: CALL VCHAR(I,25-I,128):: CALL VCHAR(I+1,25-I,132,22-I*2):: CALL VCHAR(23-I,25-I,130):: NEXT I :: RETURN

10000 DATA FFFFFFFFFFFFFFFFC3C3C3C3C3C3FFFFFFFFC0C0C0C0FFFFC3C3C0C0C0C0FFFF
10010 DATA FFFFC3C3C3C3C3C3C3C3C3C3C3C3C3C3FFFFC0C0C0C0C3C3C3C3C0C0C0C0C3C3
10020 DATA FFFF03030303FFFFC3C303030303FFFFFFFF00000000FFFFC3C300000000FFFF
10030 DATA FFFF03030303C3C3C3C303030303C3C3FFFF00000000C3C3C3C300000000C3C3

11000 DATA 0103070F1F3F7FFF80C0E0F0F8FCFEFFFF7F3F1F0F070301FFFEFCF8F0E0C080
11010 DATA FFFFFFFFFFFFFFFF0000000000000000FEFEFEFEFEFEFEFE7F7F7F7F7F7F7F7F
11020 DATA CCCC3333CCCC3333AA55AA55AA55AA55F0F0F0F0F0F0F0F00F0F0F0F0F0F0F0F
11030 DATA 0000000000000000000000000000000000000000000000000000000000000000

13000 DATA -1,0,0,1,1,0,0,-1
13010 DATA 8,2,1,4
13020 DATA 1,4,2,8
13030 DATA 2,8,4,1
13040 DATA 4,1,8,2
13050 DATA NORTH,EAST,SOUTH,WEST

 

I tried to run the program, and I get this ...

 

 

 

Link to comment
Share on other sites

Nice work--I like how you've done the dungeon walls. . .

 

Thanks! I wanted to do large bricks, but that required two patterns... my original all XB version uses DISPLAY AT to do those efficiently. I may distress the top edge of the slants like Wizard's Revenge has, haven't decided yet.

 

I decided on dark and light blue for the dungeon walls because I felt it was the best combination. Monsters will need to be other colors and I still have cyan to use for them. I considered using dark and medium red but I'd rather have reds for other things.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...