InfernalKeith Posted April 9, 2023 Share Posted April 9, 2023 I'm a little hesitant to share before it's completely done, but it's very close now, so I wanted to show off my newest game, Tollkeeper. It's a 1-2 player turn-based game in which you buy and sell acres of land, which are passed over by caravans, which pay you tolls. Your opponent is also grabbing land and collecting tolls, and when your territories overlap, it's a battle. Tollkeeper is being written to run in 16K TI BASIC and load from cassette (inspired by PixelPedant and Hell's Halls, of course). There will be AI to play against in a 1-player mode, although I don't yet know how good it'll be or what strategy it will implement. I've got the buying, selling, and all the setup and NPC caravan activity in place and I'm still sitting under 7K of code, so I might be able to do some cool stuff. You can haggle when you buy land (but not without risk), sell less desirable terrain to get better land and command more tolls, and reclaim acres destroyed by battle. You lose if you reach zero acres of land or zero coin, and the game ends after a pre-determined number of caravans have made safe passage across the kingdom. I plan to do another physical game release around Tollkeeper, this time on cassette. More about that later on. I hope to have it uploaded for you to check out soon. 15 Quote Link to comment Share on other sites More sharing options...
pixelpedant Posted April 9, 2023 Share Posted April 9, 2023 Nice. TI BASIC really wanted for more strategy/tactical/turn-based games. Given it can do lovely graphics and complex math and data structures. Just not quickly. I look forward to seeing more. 3 Quote Link to comment Share on other sites More sharing options...
ti99iuc Posted April 9, 2023 Share Posted April 9, 2023 The graphic remember me the screen of the nice Crystal Garden 4 Quote Link to comment Share on other sites More sharing options...
InfernalKeith Posted April 9, 2023 Author Share Posted April 9, 2023 8 hours ago, ti99iuc said: The graphic remember me the screen of the nice Crystal Garden Thanks! That's a game that could use a major rewrite, if I ever had time. One day. 4 Quote Link to comment Share on other sites More sharing options...
InfernalKeith Posted April 12, 2023 Author Share Posted April 12, 2023 Update: I'm finishing up the fighting routine now - it's a pretty simple dice-roll type thing. I also moved the two players' starting territory closer together, because it was taking a long time to get to any conflict between players and without that, it was frankly a little boring. I'm no longer quite sure I'll be able to fit all the AI I want into one piece of code that'll still run on unexpanded real iron (which is the goal here). I think I might do like the old tape games that came with a keyboard version on one side of the tape, and a joystick version on the other -- only my two versions will be "red AI" and "blue AI." One will be more concerned with defense, fortification, and maximizing the tolls it collects, while the other will be more of a warmonger and start blitzing you as soon as it's able to geographically reach you. My goal is to post a gameplay video tomorrow and to have at least some semblance of one of the AI's done. I've been doing a lot of cleanup as I go, code-wise, so hopefully there won't be any ugly surprises in testing and I can get this thing uploaded sooner than later. I'm pretty happy with how it's turning out. 5 Quote Link to comment Share on other sites More sharing options...
pixelpedant Posted April 12, 2023 Share Posted April 12, 2023 One other option if you get desperate and you've got a fair number of custom patterns taking up space in your program is you can load your custom patterns into the range from 128 to 159 (which is never reset by BASIC itself) with one program (either on the other side or preceding the main program on the same one), then load and run the main program after. This gives you 32 custom patterns which cost you exactly zero program memory. 2 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted April 12, 2023 Share Posted April 12, 2023 4 hours ago, pixelpedant said: One other option if you get desperate and you've got a fair number of custom patterns taking up space in your program is you can load your custom patterns into the range from 128 to 159 (which is never reset by BASIC itself) with one program (either on the other side or preceding the main program on the same one), then load and run the main program after. This gives you 32 custom patterns which cost you exactly zero program memory. This is a good idea, and one that I never thought of. Unfortunately it is not quite as simple as that. You can copy and paste this into BASIC to see what happens. The first program defines characters 128 to 159 and prints them on the screen. When the second program runs, the first 4 characters are messed up. Then the stack gets filled up and the rest of the characters are trashed. NEW 10 FOR I=128 TO 159 20 CALL CHAR(I,"FF818181818181FF") 25 PRINT CHR$(I); 30 NEXT I RUN NEW 90 REM CALL CHAR(159,"FFFFFFFFFFFFFFFF") 100 FOR I=128 TO 159 110 PRINT CHR$(I); 120 NEXT I 130 A$="HELLO WORLD" 140 GOTO 130 RUN If you take the REM out of line 90 then all the characters are left alone and it works as expected. So far so good. The big problem is this. I saved the second program to disk as DSK3.PP If you run the first program to redefine the characters, then OLD DSK3.PP will overwrite the redefined characters as it loads the program to VDP ram starting at >0700 This seems to be a fatal flaw unless there is a solution for this. 2 Quote Link to comment Share on other sites More sharing options...
InfernalKeith Posted April 12, 2023 Author Share Posted April 12, 2023 8 hours ago, pixelpedant said: One other option if you get desperate and you've got a fair number of custom patterns taking up space in your program is you can load your custom patterns into the range from 128 to 159 (which is never reset by BASIC itself) with one program (either on the other side or preceding the main program on the same one), then load and run the main program after. This gives you 32 custom patterns which cost you exactly zero program memory. If I was gonna take that step, I could go for broke and follow the path of Atlantis and Not-Polyoptics' Hordes, and load all the data from a file after the program on tape. Part of me thinks that's a really big ask of anyone playing in 2023, but another part of me recognizes that even people who buy it on tape are likely to play it once or twice on real iron and then just load it in an emulator anyway. It miiight not come to that. I did just get a MEMORY FULL but so far CALL FILES has freed up enough space to work, and I haven't even deleted REM statements or made any serious code compromises yet, so it may all fit. Do y'all recall if there's one thread (or page, or scanned article somewhere) that acts as sort of a master repository of how many bytes each statement uses? Or how many bytes CALL FILES actually saves? 3 Quote Link to comment Share on other sites More sharing options...
+OLD CS1 Posted April 12, 2023 Share Posted April 12, 2023 1 hour ago, InfernalKeith said: Do y'all recall if there's one thread (or page, or scanned article somewhere) that acts as sort of a master repository of how many bytes each statement uses? Or how many bytes CALL FILES actually saves? Three DSK buffers consumes 2,088 bytes of VDP RAM. You can figure out the bytes used in statements by thinking in tokenization. CALL is a single token, while CALL SOUND is a token followed by the ASCII representation of the word SOUND, &c. Without looking, strings are a token, length, string, null byte. Numbers are token, length, number as text. Variables are just the variable names, which is why setting @=[some frequently-used number] then using @ in your program to replace that number consumes fewer bytes over-all. Everything on a line is tokenized except for non-literal (quoted) spaces, or spaces in a REM statement. There have been BASIC and Extended BASIC tokens lists posted around here, including in source code posted by @RXB. Not sure from where I got this, but here. TI-99 Extended BASIC Tokens.ods You can also see the effects of a program in memory using Classic99's debugger looking into VDP RAM from the top. 4 1 Quote Link to comment Share on other sites More sharing options...
RXB Posted April 12, 2023 Share Posted April 12, 2023 HERE IS THE TOKEN LIST FROM XB GPL SOURCE. Spoiler <0140> *********************************************************** <0141> * BASIC TOKEN TABLE <0142> * EQU >80 spare token <0143> 0081 ELSEZ EQU >81 ELSE <0144> 0082 SSEPZ EQU >82 :: <0145> 0083 TREMZ EQU >83 $ <0146> 0084 IFZ EQU >84 IF <0147> 0085 GOZ EQU >85 GO <0148> 0086 GOTOZ EQU >86 GOTO <0149> 0087 GOSUBZ EQU >87 GOSUB <0150> 0088 RETURZ EQU >88 RETURN <0151> 0089 DEFZ EQU >89 DEF <0152> 008A DIMZ EQU >8A DIM <0153> 008B ENDZ EQU >8B END <0154> 008C FORZ EQU >8C FOR <0155> 008D LETZ EQU >8D LET <0156> 008E BREAKZ EQU >8E BREAK <0157> 008F UNBREZ EQU >8F UNBREAK <0158> 0090 TRACEZ EQU >90 TRACE <0159> 0091 UNTRAZ EQU >91 UNTRACE <0160> 0092 INPUTZ EQU >92 INPUT <0161> 0093 DATAZ EQU >93 DATA <0162> 0094 RESTOZ EQU >94 RESTORE <0163> 0095 RANDOZ EQU >95 RANDOMIZE <0164> 0096 NEXTZ EQU >96 NEXT <0165> 0097 READZ EQU >97 READ <0166> 0098 STOPZ EQU >98 STOP <0167> 0099 DELETZ EQU >99 DELETE <0168> 009A REMZ EQU >9A REM <0169> 009B ONZ EQU >9B ON <0170> 009C PRINTZ EQU >9C PRINT <0171> 009D CALLZ EQU >9D CALL <0172> 009E OPTIOZ EQU >9E OPTION <0173> 009F OPENZ EQU >9F OPEN <0174> 00A0 CLOSEZ EQU >A0 CLOSE <0175> 00A1 SUBZ EQU >A1 SUB <0176> 00A2 DISPLZ EQU >A2 DISPLAY <0177> 00A3 IMAGEZ EQU >A3 IMAGE <0178> 00A4 ACCEPZ EQU >A4 ACCEPT <0179> 00A5 ERRORZ EQU >A5 ERROR <0180> 00A6 WARNZ EQU >A6 WARNING <0181> 00A7 SUBXTZ EQU >A7 SUBEXIT <0182> 00A8 SUBNDZ EQU >A8 SUBEND <0183> 00A9 RUNZ EQU >A9 RUN <0184> 00AA LINPUZ EQU >AA LINPUT <0185> * EQU >AB spare token (LIBRARY) <0186> * EQU >AC spare token (REAL) <0187> * EQU >AD spare token (INTEGER) <0188> * EQU >AE spare token (SCRATCH) <0189> * EQU >AF spare token <0190> 00B0 THENZ EQU >B0 THEN <0191> 00B1 TOZ EQU >B1 TO <0192> 00B2 STEPZ EQU >B2 STEP <0193> 00B3 COMMAZ EQU >B3 , <0194> 00B4 SEMICZ EQU >B4 ; <0195> 00B5 COLONZ EQU >B5 : <0196> 00B6 RPARZ EQU >B6 ) <0197> 00B7 LPARZ EQU >B7 ( <0198> 00B8 CONCZ EQU >B8 & (CONCATENATE) <0199> * EQU >B9 spare token <0200> 00BA ORZ EQU >BA OR <0201> 00BB ANDZ EQU >BB AND <0202> 00BC XORZ EQU >BC XOR <0203> 00BD NOTZ EQU >BD NOT <0204> 00BE EQUALZ EQU >BE = <0205> 00BF LESSZ EQU >BF < <0206> 00C0 GREATZ EQU >C0 > <0207> 00C1 PLUSZ EQU >C1 + <0208> 00C2 MINUSZ EQU >C2 - <0209> 00C3 MULTZ EQU >C3 * <0210> 00C4 DIVIZ EQU >C4 / <0211> 00C5 CIRCUZ EQU >C5 ^ <0212> * EQU >C6 spare token <0213> 00C7 STRINZ EQU >C7 QUOTED STRING <0214> 00C8 UNQSTZ EQU >C8 UNQUOTED STRING <0215> 00C8 NUMZ EQU >C8 ALSO NUMERICAL STRING <0216> 00C8 NUMCOZ EQU >C8 ALSO UNQUOTED STRING <0217> 00C9 LNZ EQU >C9 LINE NUMBER CONSTANT <0218> 00CA EOFZ EQU >CA EOF <0219> 00CB ABSZ EQU >CB ABS <0220> 00CC ATNZ EQU >CC ATN <0221> 00CD COSZ EQU >CD COS <0222> 00CE EXPZZ EQU >CE EXP <0223> 00CF INTZ EQU >CF INT <0224> 00D0 LOGZ EQU >D0 LOG <0225> 00D1 SGNZZ EQU >D1 SGN <0226> 00D2 SINZ EQU >D2 SIN <0227> 00D3 SQRZ EQU >D3 SQR <0228> 00D4 TANZ EQU >D4 TAN <0229> 00D5 LENZ EQU >D5 LEN <0230> 00D6 CHRZZ EQU >D6 CHR$ <0231> 00D7 RNDZ EQU >D7 RND <0232> 00D8 SEGZZ EQU >D8 SEG$ <0233> 00D9 POSZ EQU >D9 POS <0234> 00DA VALZ EQU >DA VAL <0235> 00DB STRZZ EQU >DB STR$ <0236> 00DC ASCZ EQU >DC ASC <0237> 00DD PIZ EQU >DD PI <0238> 00DE RECZ EQU >DE REC <0239> 00DF MAXZ EQU >DF MAX <0240> 00E0 MINZ EQU >E0 MIN <0241> 00E1 RPTZZ EQU >E1 RPT$ <0242> * EQU >E2 unused <0243> * EQU >E2 unused <0244> * EQU >E3 unused <0245> * EQU >E4 unused <0246> * EQU >E5 unused <0247> * EQU >E6 unused <0248> * EQU >E7 unused <0249> 00E8 NUMERZ EQU >E8 NUMERIC <0250> 00E9 DIGITZ EQU >E9 DIGIT <0251> 00EA UALPHZ EQU >EA UALPHA <0252> 00EB SIZEZ EQU >EB SIZE <0253> 00EC ALLZ EQU >EC ALL <0254> 00ED USINGZ EQU >ED USING <0255> 00EE BEEPZ EQU >EE BEEP <0256> 00EF ERASEZ EQU >EF ERASE <0257> 00F0 ATZ EQU >F0 AT <0258> 00F1 BASEZ EQU >F1 BASE <0259> * EQU >F2 spare token (TEMPORARY) <0260> 00F3 VARIAZ EQU >F3 VARIABLE <0261> 00F4 RELATZ EQU >F4 RELATIVE <0262> 00F5 INTERZ EQU >F5 INTERNAL <0263> 00F6 SEQUEZ EQU >F6 SEQUENTIAL <0264> 00F7 OUTPUZ EQU >F7 OUTPUT <0265> 00F8 UPDATZ EQU >F8 UPDATE <0266> 00F9 APPENZ EQU >F9 APPEND <0267> 00FA FIXEDZ EQU >FA FIXED <0268> 00FB PERMAZ EQU >FB PERMANENT <0269> 00FC TABZ EQU >FC TAB <0270> 00FD NUMBEZ EQU >FD # <0271> 00FE VALIDZ EQU >FE VALIDATE <0272> * EQU >FF ILLEGAL VALUE 2 Quote Link to comment Share on other sites More sharing options...
InfernalKeith Posted May 21, 2023 Author Share Posted May 21, 2023 After a few more bumps and bruises trying to save memory, and cutting out some things I aesthetically hate to lose but which serve no practical function (no one needs a <q>uit menu option and a "thanks for playing" message), the game now has combat, full turns, and it runs with CALL FILES (0) in unexpanded BASIC. I chose to "front load" the BASIC pain of setup (which, if you're playing in Classic99, can be hacked by using Overdrive until setup is complete). Once the game screen is generated, gameplay moves along at a fairly brisk pace for BASIC. I have some cosmetic things to fix and then my last big hurdle -- trying to squeeze in some AI for the blue player for a 1-player game. Again, it won't be as visually pretty as I'd like, but I have a plan to make the computer take its turns fairly quickly and with enough forethought to make the game interesting. I can only imagine how amazing and powerful Extended BASIC and 32K of memory expansion is gonna feel after I finally finish this. 7 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.