-
Posts
1,891 -
Joined
-
Last visited
Content Type
Profiles
Forums
Blogs
Gallery
Events
Store
Posts posted by adamantyr
-
-
18 minutes ago, Ksarul said:
You could eliminate a lot of them if you defaulted instances with a T corridor to an L unless it fails to connect the room to the grid. . .
There aren't any L corridors in Tunnels of Doom. Just T's, four-way, up/down and left/right.
-
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-
3
-
-
3 hours ago, jstimson said:
I assume you've taken a gander at this site for any potential leads?
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.
-
1
-
-
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.
-
2
-
-
52 minutes ago, Tursi said:
You'll probably get more efficient code from not seeing the original source anyway. The programming styles we see today are pretty different from what we did in '81, not to mention TOD would have strictly followed the TI rules that we blatantly ignore today.
It would be really cool to see a new driver for the games... but it won't be me.
You have done far MORE than your fair share for the TI community, Mike. I bow to you.
-
1
-
-
1 hour ago, Gary from OPA said:
Yes, a new TOD would be great idea. I might be able to help produce a proper commented GPL disassembly. I will also search my archives and see if it's been partly done already.
That would be awesome!
-
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?
-
13
-
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.
-
4
-
-
On 9/9/2023 at 7:32 AM, senior_falcon said:
I included APERTURE, by Adamantyr with the XB game developer's package, and use it as an example of how to compile a program.
I did not ask for permission to do this, and now realize that I should have done so. If this is a problem then I will remove it and substitute something else.
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.
-
1
-
-
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!
-
4
-
-
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.
-
6
-
-
On 6/19/2023 at 5:20 AM, TheMole said:
I think I have the core ghost catching mechanic implemented. It's not 100% identical to my two main sources of inspiration (SMS and C64), but it comes pretty close, imho...
Note that I'm showing a ghost in each location to facilitate testing for now, things like haunted buildings, the PK energy progression and getting paid for catching ghosts aren't implemented yet. Wanted to get the more challenging technical bits done first. It turns out that getting the whole state machine implemented was a bit more challenging than I thought... from laying down the trap (which turns into characters to keep the 4-sprites-per-line limit under control) over positioning the men and ultimately animating the victory or loss condition... all these "phases" are treated as different states in the game engine.
Lastly, just wanted to point out that I used Bill Murray's "he slimed me" quote from the movie in lieu of the one used on the C64 to keep the quality as high as possible.
Hope you guys like it!
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.
-
3
-
-
16 hours ago, TheMole said:
So, quick question to those of you that know and have played the game... I'm on the fence about the approach for the driving segments. I could go home-computer style, where you have a huge car filling almost the entire screen, and the game play is limited to potentially vacuuming ghosts, as shown here:
I've heard people call this part of the game boring (although honestly, I kinda like the more chill gameplay myself), so the console versions spruced it up a bit, where you also have to avoid cars and obstacles (and in the NES version even pick up fuel barrels), and the graphical presentation has been changed quite a bit:
Which would you prefer?
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.
-
1 hour ago, TheMole said:
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.
-
1
-
-
23 hours ago, TheMole said:
So, here are some mock-ups showing some of the game's screens. These are all made in Gimp and haven't been put into the game yet, but should all work within the restrictions of the tms9918a.
A lot of the inspiration for the graphics comes from the Master System version, but I'm also looking at the MSX and C64 versions closely for each part of the game. Any feedback is welcome!
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.
-
1
-
-
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?)
-
2
-
-
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.)
-
2
-
-
15 hours ago, llabnip said:
With three cups of coffee and some help from @Tursi (mostly to eliminate things to try) I've got a discovery. ROA is making use of the 9901 timer. When I did my re-write, I didn't understand that very well - and based on some experiments and some reading, it looked like it was mostly used for Cassette IO handling which I wasn't supporting. So I simplified my handling of anything 9901 timer-based... and by simplified I mean I almost totally ignore it. I suspect ROA is one of those rare games that makes use of it. I don't know if it enables the timer interrupt or if it's just setting and checking the countdown register... but this is my current best guess as to what's going wrong with DS99.
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.
-
5
-
-
On 1/30/2023 at 10:23 AM, Asmusr said:
Regarding 4MB SAMS, the hardware only exists in very low numbers, and I'm pretty sure Realms of Antiquity does not depend on that.
Yeah, it runs on the 1mb version. It may even break on the 4mb version.
-
On 1/27/2023 at 2:08 PM, InfiniteTape said:
Realms of Antiquity. It's a modern TI release by @adamantyr. It's not free, but it may push your implementation in new ways. http://quixotic.adamantyr.com/roa.htm
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
-
2
-
-
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.
-
7
-
1
-
-
Cool to see this available for the TI as well, thanks Evie!
-
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*
-
Excellent! I just ordered a copy.
-
3
-







New Tunnels of Doom engine?
in TI-99/4A Development
Posted
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.