Jump to content
IGNORED

TOLLKEEPER - new BASIC game in development


Recommended Posts

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.

 

tollkeeper4.jpg

  • Like 15
Link to comment
Share on other sites

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.

tollkeeper5.jpg

  • Like 5
Link to comment
Share on other sites

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. 

  • Like 2
Link to comment
Share on other sites

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.

 

  • Like 2
Link to comment
Share on other sites

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?

  • Like 3
Link to comment
Share on other sites

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.

  • Like 4
  • Thanks 1
Link to comment
Share on other sites

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

 

  • Like 2
Link to comment
Share on other sites

  • 1 month later...

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.

 

tollkeeper6.jpg

  • Like 7
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...