Jump to content

adamantyr

+AtariAge Subscriber
  • Posts

    1,891
  • Joined

  • Last visited

Everything posted by adamantyr

  1. I get the feeling he may have over-engineered this one. I was able to deterministically connect every room to a corridor without having to store much other than "this room has this many connections". I would guess he MUST consider the room's quadrant (top, bottom, left right) as well since the room coordinates are stored to retain that data. Otherwise why wouldn't he have just used the two bytes to store a row and column? I'd probably use those data points to make sure it is biased to "head to center" so a room in the top left quadrant would try and go down and right, for example. Also, his algorithm doesn't work if rooms are too far. A map I created randomly put two rooms along the topmost row and they failed to connect to the rest of the dungeon when the TOD cart rendered it. All in all, this exercise is giving me confidence I can write a corridor algorithm that works well. It may mean a new engine renders a different maze, but that's fine.
  2. There aren't any L corridors in Tunnels of Doom. Just T's, four-way, up/down and left/right.
  3. So I wrote up a prototype map generation in Extended BASIC to test out making corridors. My initial one definitely connects all the rooms but honestly makes WAY too many corridors: Here's the code for the interested. Next step is to make it a bit less thirsty. 100 RANDOMIZE 1982 :: OPTION BASE 1 :: DIM RTB(26),RLR(26),RY(26),RX(26),RD(26),RYR(4),RYA(4),RXR(4),RXA(4) 110 CALL CLEAR :: CALL SCREEN(4):: CALL COLOR(9,6,15,10,6,15):: FOR I=96 TO 108 STEP 4 :: READ C$ :: CALL CHAR(I,C$):: NEXT I 120 FOR I=1 TO 4 :: READ RYR(I),RYA(I),RXR(I),RXA(I):: NEXT I :: FOR I=1 TO 19 :: CALL HCHAR(I,3,107,28):: NEXT I 130 R=1 :: GOSUB 1000 :: CALL VCHAR(Y,X,104):: RTB(R)=TB :: RLR(R)=LR :: RY(R)=Y :: RX(R)=X 140 FOR R=3 TO 4 :: GOSUB 1000 :: CALL VCHAR(Y,X,105):: RTB(R)=TB :: RLR(R)=LR :: RY(R)=Y :: RX(R)=X :: NEXT R 150 FOR R=5 TO 6 :: GOSUB 1000 :: CALL VCHAR(Y,X,106):: RTB(R)=TB :: RLR(R)=LR :: RY(R)=Y :: RX(R)=X :: NEXT R 160 FOR R=7 TO 26 :: GOSUB 1000 :: CALL VCHAR(Y,X,103):: RTB(R)=TB :: RLR(R)=LR :: RY(R)=Y :: RX(R)=X :: NEXT R 200 CALL SCREEN(10):: FOR R=1 TO 26 :: IF RY(R)=0 THEN 290 201 FOR R2=1 TO 26 :: IF R=R2 THEN 210 :: IF RY(R2)=0 THEN 210 :: IF RX(R)<>RX(R2) THEN 210 202 X=RX(R):: IF RY(R) < RY(R2) THEN Y=1+RY(R):: YS=Y ELSE Y=1+RY(R2) :: YS=Y 203 CALL GCHAR(Y,X,G):: IF G=107 THEN Y=Y+1 :: GOTO 203 ELSE CALL VCHAR(YS,X,97,Y-YS) 210 NEXT R2 290 NEXT R 300 CALL SCREEN(14):: FOR R=1 TO 26 :: IF RY(R)=0 THEN 390 301 FOR R2=1 TO 26 :: IF R=R2 THEN 310 :: IF RY(R2)=0 THEN 310 :: IF RY(R)<>RY(R2) THEN 310 302 Y=RY(R):: IF RX(R) < RX(R2) THEN X=1+RX(R) :: XS=X ELSE X=1+RX(R2) :: XS=X 303 CALL GCHAR(Y,X,G):: IF G=107 THEN X=X+1 :: GOTO 303 ELSE CALL HCHAR(Y,XS,96,X-XS) 304 IF G=97 THEN CALL VCHAR(Y,X,101) 310 NEXT R2 390 NEXT R 400 CALL SCREEN(11):: GOSUB 500 :: CALL SCREEN(4) 410 GOTO 410 500 FOR R=1 TO 26 :: IF RD(R)>1 OR RY(R)=0 THEN 990 510 CC=0 :: UC=0 :: DC=0 :: LC=0 :: RC=0 515 CALL GCHAR(RY(R)-1,RX(R),GU):: CALL GCHAR(RY(R)+1,RX(R),GD):: CALL GCHAR(RY(R),RX(R)-1,GL):: CALL GCHAR(RY(R),RX(R)+1,GR) 520 IF GR=97 THEN CALL VCHAR(RY(R),RX(R)+1,101):: CC=CC+1 :: GOTO 530 521 IF GR=102 THEN CALL VCHAR(RY(R),RX(R)+1,98):: CC=CC+1 :: GOTO 530 522 IF GR=107 THEN RC=1 530 IF GL=97 THEN CALL VCHAR(RY(R),RX(R)-1,102):: CC=CC+1 :: GOTO 540 531 IF GL=102 THEN CALL VCHAR(RY(R),RX(R)-1,98):: CC=CC+1 :: GOTO 540 532 IF GL=107 THEN LC=1 540 IF GU=96 THEN CALL VCHAR(RY(R)-1,RX(R),100):: CC=CC+1 :: GOTO 550 541 IF GU=99 THEN CALL VCHAR(RY(R)-1,RX(R),98):: CC=CC+1 :: GOTO 550 542 IF GU=107 THEN UC=1 550 IF GD=96 THEN CALL VCHAR(RY(R)+1,RX(R),99):: CC=CC+1 :: GOTO 560 551 IF GD=100 THEN CALL VCHAR(RY(R)+1,RX(R),98):: CC=CC+1 :: GOTO 560 552 IF GD=107 THEN DC=1 560 RD(R)=CC :: IF CC>=2 THEN 990 600 IF RC=0 OR CC>=2 THEN 700 ELSE Y=RY(R):: X=RX(R):: XS=X+1 610 X=X+1 :: CALL GCHAR(Y,X,G):: IF G=107 THEN 610 620 IF G=32 THEN 700 630 IF G>102 THEN CE=G :: GOTO 660 640 IF (G=101 OR G=102) THEN CE=98 :: GOTO 660 650 IF G=97 THEN CE=101 660 CALL HCHAR(Y,XS,96,X-XS):: CALL HCHAR(Y,X,CE):: CC=CC+1 700 IF LC=0 OR CC>=2 THEN 800 ELSE Y=RY(R):: X=RX(R):: XS=X-1 710 X=X-1 :: CALL GCHAR(Y,X,G):: IF G=107 THEN 710 720 IF G=32 THEN 800 730 IF G>102 THEN CE=G :: GOTO 760 740 IF (G=101 OR G=102) THEN CE=98 :: GOTO 760 750 IF G=97 THEN CE=102 760 CALL HCHAR(Y,X+1,96,XS-X):: CALL HCHAR(Y,X,CE):: CC=CC+1 800 IF UC=0 OR CC>=2 THEN 900 ELSE Y=RY(R):: X=RX(R):: YS=Y-1 810 Y=Y-1 :: IF Y=0 THEN 900 ELSE CALL GCHAR(Y,X,G):: IF G=107 THEN 810 830 IF G>102 THEN CE=G :: GOTO 860 840 IF (G=99 OR G=100) THEN CE=98 :: GOTO 860 850 IF G=96 THEN CE=100 860 CALL VCHAR(Y,X,97,1+YS-Y):: CALL VCHAR(Y,X,CE):: CC=CC+1 900 IF DC=0 OR CC>=2 THEN 990 ELSE Y=RY(R):: X=RX(R):: YS=Y+1 910 Y=Y+1 :: CALL GCHAR(Y,X,G):: IF G=107 THEN 910 920 IF G=32 THEN 990 930 IF G>102 THEN CE=G :: GOTO 960 940 IF (G=99 OR G=100) THEN CE=98 :: GOTO 960 950 IF G=96 THEN CE=99 960 CALL VCHAR(YS,X,97,Y-YS):: CALL VCHAR(Y,X,CE):: CC=CC+1 990 NEXT R :: RETURN 1000 TB=INT(RND*2)+1 :: LR=INT(RND*2)+1 1001 IF R>4 THEN Y=INT(RND*RYR(TB))+RYA(TB):: X=INT(RND*RXR(LR))+RXA(LR) ELSE Y=INT(RND*RYR(TB+2))+RYA(TB+2):: X=INT(RND*RXR(LR+2))+RXA(LR+2) 1002 CALL GCHAR(Y,X,G):: IF G<>107 THEN 1001 1003 CALL GCHAR(Y-1,X,G):: IF G<>107 THEN 1001 :: CALL GCHAR(Y+1,X,G):: IF G<>107 THEN 1001 1004 CALL GCHAR(Y,X-1,G):: IF G<>107 THEN 1001 :: CALL GCHAR(Y,X+1,G):: IF G<>107 THEN 1001 1005 RETURN 10000 DATA 000000FFFF0000001818181818181818181818FFFF181818181818FFFF000000 10001 DATA 000000FFFF181818181818F8F81818181818181F1F181818FF81BDA5A5BD81FF 10002 DATA 7EE7FFC3FF81FF7E7EFF81FFC3FFE77E3C66DBBDBDDB663C0000000000000000 10003 DATA 8383838383838383C0C0C0C0C0C0C0C000000000000000000000000000000000 11000 DATA 8,2,16,4 11001 DATA 8,10,10,20 11002 DATA 5,5,13,7 11003 DATA 5,10,7,20
  4. Oh yeah, I got that one from years ago. He doesn't provide source, but Java bytecode is easy to disassemble. I'm not sure he uses the same algorithm or his own, though.
  5. Oh yes, I found the first part of his article awhile back (I even posted on it), but I forgot he does talk about the algorithm a bit. Confirmed what I thought about verticals always being drawn! I just noticed yesterday that corridors only come as straights, T's, or a cross. There's no corner pieces because there wasn't quite enough graphic room to store them. It's definitely a feature-centric algorithm. I'll do some prototyping and see if I can get something going. I mainly would want the maps to match what the original engine would generate, but if it at least makes playable maps that could be good enough.
  6. You have done far MORE than your fair share for the TI community, Mike. I bow to you.
  7. Hey all, Recently I got an urge to play a 10-level Tunnels of Doom game again, so I fired one up on Classic99. (For the record, successful game! My rogue ended up with triple digit hit points.) As I played, I noticed flaws that always irked me. A mistaken keystroke causes you to lose your turn, or even canceling a ranged weapon. The weird artifacts, like monsters attempting and failing to use special attacks. The SLOW generation of the 3D view. Then I found the truly excellent TOD guide by Michael Vepraukas, which is a gold mine on how the game file is structured. And it got me thinking, what if I could write a new engine in 100% TMS9900 assembly that could replicate the original game engine but with refinements and corrections, AND could also drive ANY of the TOD games? The big challenge, really, is that there's no source available for the game. GPL is an eclectic thing, and when I tried using the GPL disassembler on a cartridge binary, it's 2nd line was a CALL to an area in the 32k expansion. Clearly not working. MOST of the game engine could be replicated without source, there's just two major hurdles: The basic attack/defense mechanics. These can probably be gleaned through observation, but it may take a lot of work to tune it to match the original engine's style. (I notice, for example, that the miss rate is inordinately high.) Map corridors. Due to lack of space, the corridors for floors are algorithmically generated each time to descend or ascend. Replicating this exactly is crucial. So far based on observation, the one thing I noticed is that rooms that are aligned vertically are always connected. Any interest in this? Any insights or suggestions?
  8. On my PC, I like using GraphiCV, a tool developed in Java by @unhuman. It lets you do not only sprites but layer up to four of them on top of each other. You can also do bitmap graphics. For RoA, I rolled my own sprite editor on the TI itself that loaded and saved data from and to the binary file directly, so I could make quick edits as needed.
  9. I recall someone asking me in the past if they could compile it and I asked them not to, because I felt the game was written for and balanced to the speed of TI-Basic. But I'm all right with it, so long as someone doesn't complain the game's too hard because certain puzzles relied on the slowness to give you time to react.
  10. Latest version was released a few days ago.... I'm pretty sure the game is solid and stable now. Anyone who was holding off on playing, this is the time!
  11. I would definitely focus on game play and what you find fun and challenging over "stupid and frustrating". That is the hallmark of a game designer over a copier.
  12. Nice work! I would definitely test the speech out on hardware; the emulators all use a slightly later generation core. Also, please make sure music can be disabled. While I enjoy the tune, it's nice to have the option to not listen to it non-stop. Plus you could then add in some sound effects for the proton guns, the trap, etc.
  13. I only ever played the C64 version myself. I think it really depends on if you want to implement all the various car upgrades and different models of car. If you do, I'd stick with the passive version. If not, then the small mini-game of dodging cars and grabbing fuel works.
  14. I think model after the C64 but lose the center column, go single color, but have it rotate color rapidly between red, blue and yellow. I used color rotation in RoA frequently to zazz up single color sprites at low cost.
  15. Excellent graphic work! I'm very excited to see the finished product. I would say using a consistent color for the tops of buildings will help users navigate the main map easier; most of the ports only use a limited number of colors anyway. Looking at the MSX screenshots, I'm surprised at how pedestrian it looks. Definitely shoot for the stars; the Sega Master System has a much better appearance.
  16. Glad to see you are free, Gary! I almost put a reference to Oasis Pensive Abjucators in RoA, but I thought there was no real way to do it that would work. (A dreamy merchant at an oasis?)
  17. I found that software sprite rotation... isn't great. I wrote a small test program and found that it caused a lot of blinking that was pretty harsh. FORTUNATELY you should be okay, because it's only horizontal that's the problem. If you only use four sprite (two proton streams and two for the target ghost) you should be okay. You DO have 32 sprites to work with, although I would warn you can't use half-bitmap/enhanced graphics mode in that case, only full bitmap, because the table masks mess up the sprites and you're limited to 8 unique sprites. (If you use 9 or higher, they just repeat the first eight.)
  18. It does use the timer, but it's for random numbers. The clock runs so fast it's usable in any state. (I originally used the VDP timer, but it produced predictable patterns for battlemap generation.) I'm not sure if that would cause the game to not work, though, unless even trying to set the CRU bits to access it caused your emulator to crash. Also, for the 180K version, you have to use the cartridge binary, and put all the rest of the files from the game disk on a single disk, and split the world disks into four disks. And be sure to configure their location in the configuration menu.
  19. Yeah, it runs on the 1mb version. It may even break on the 4mb version.
  20. Yeah, developer of Realms of Antiquity here. In order for it to run, you will need to emulate the SAMS card, which provides 1024mb of CPU memory to the base TI. Hardware details can be found here: http://www.unige.ch/medecine/nouspikel/ti99/superams.htm
  21. BLWP, by having an isolated register set, is useful because it's sort of like a method in a high-end language like Java, C, C#, etc. For BL/RT, I usually set up an internal stack and burn R10 as a pointer for it, so I can push and pop return addresses off if needed. That way BL routines can call other BL routines but still work their way back to the original caller. What I did find when coding Realms of Antiquity was that I'd frequently run into issues where I was using registers to hold specific values at the top of a return stack, and either I'd end up running out of registers to use or worse, accidentally use one and cause a bug. That's where I would convert some subroutines into BLWP versions, because then they operated independently. Also, I've used register sets in the regular CPU memory areas other than the scratch pad and not had performance problems. It's all about the context of what you're using them for.
  22. Cool to see this available for the TI as well, thanks Evie!
  23. A fantastic job, sir! I salute you. If Hell's Halls had been in the BASIC contest years ago, you'd have won, hands down! Sadly my game crashed with MEMORY FULL a bit ago, after I reached the 3rd level. I was playing in emulation; I guess loading the BIN file doesn't perform a call FILES(1) operation. *sigh*
×
×
  • Create New...