Autosaving with Batch-based Text Adventure Game?

1.6k Views Asked by At

I'm making a Text Adventure game using batch-script, and I would like to know if there is a way to program it to automatically save at a certain point.
I'm asking this as I recently read that a youtuber once coded one of his RPGs to autosave, though he never revealed it publicly.

So is there a way to make a batch RPG/text adventure publish autosaves? If so, how do you do it?

3

There are 3 best solutions below

0
On

This is actually quite simple, although it consumes a large amount of space, depending on how many variables you wish to save. You want to have another batch file in the same directory as the batch file you are running. This batch file can be titled save.bat, variables.bat, or whatever. For every action completed, you want it to save the variables to that batch file. For instance:

@echo off
call save.bat
:direction
cls
echo.
echo Would you like to
echo 1) go north
echo 2) go south
set /p answer=:
if %answer% equ 1 goto north
if %answer% equ 2 goto south
cls
echo.
echo That command isn't recognized.
echo.
pause
goto direction
:north
echo set /a money=%money%>>save.bat
echo set /a health=%health%>>save.bat
echo set /a mana=%mana%>>save.bat
cls
echo.
echo You head North.
echo.
pause
exit
:south
echo set /a money=%money%>>save.bat
echo set /a health=%health%>>save.bat
echo set /a mana=%mana%>>save.bat
cls
echo.
echo You head South.
echo.
pause
exit

You notice how it saves the variables to save.bat, which is then called at the beginning of the game. The >> indicate that it's adding a new line to the file. If you just use a single > it will delete everything from before, and add the variable to the file. Although you will have to save the variables after every action, it's worth it. If you would like to conserve space, you could do this:

@echo off
call save.bat
:direction
cls
echo.
echo Would you like to
echo 1) go north
echo 2) go south
set /p answer=:
if %answer% equ 1 goto north
if %answer% equ 2 goto south
cls
echo.
echo That command isn't recognized.
echo.
pause
goto direction
:north
call autosave.bat
cls
echo.
echo You head North.
echo.
pause
exit
:south
call autosave.bat
cls
echo.
echo You head South.
echo.
pause
exit

And inside of autosave.bat:

echo set /a money=%money%>>save.bat
echo set /a health=%health%>>save.bat
echo set /a mana=%mana%>>save.bat

So yeah, that's how you can autosave the game.

1
On

There are scores, perhaps hundreds of languages that are better suited to adventure gaming than MS-DOS batch scripts. Try Python, TCL, Lua, Java, C#, or any other language besides batch. An object oriented language is often used for fantasy adventure games because of their ability to do modelling well. A language with a persistence framework (such as Hibernate) might be handy for auto-save. But that tends to involve storing data in a relational database, which are also good for modelling. But don't try to bite off too much at a time.

Since you are in the frame of mind to try a text based game, with a very simple language. You might do well with TCL. But as I said, there are scores of good options. Batch is not considered one of them.

5
On

No reason go go haring off in pursuit of others' obsession with their one-true-way. Like any language, batch has its quirks, but the fundamental methodology is common.

With procedural languages, I've followed a similar structure for decades. The key is to simply only ever have ONE procedure that interacts with the user. The rest of the program thenbecomes a state-machine, directed from one state to the next in response to the user's input. It may take a little getting used to, but I've successfully (and quickly) developed programs using this principle in batch, cobol, pascal, basic, progress, mantis and others.

@ECHO OFF
SETLOCAL
SET state=0
SET "savefile="
:mainloop
CALL :state%state%
IF %state% neq 999999 GOTO mainloop
GOTO :EOF

::
:: USER I/O
::

:userio
IF NOT DEFINED savefile GOTO useriolp
set>%savefile%
:useriolp
SET "response="
SET /p response="%message% ? "
IF NOT DEFINED response GOTO useriolp
SET response=%response: =_%
FOR %%r IN (EXIT quit) DO IF /i %response%==%%r SET state=999999&GOTO :EOF
SET "state="
FOR %%r IN (%vr%) DO IF DEFINED state (
 IF /i %%r==%response% GOTO :EOF
 SET "state="
) ELSE (SET state=%%r)
IF DEFINED state GOTO :eof
ECHO Invalid response
GOTO useriolp

::State 0 - get username

:state0
SET "vr=100"
SET message=Your name
GOTO userio

:: State 100 - have username.
:: Load user's savefile if it exists

:state100
SET savefile=%response%
IF exist %savefile% GOTO S100.1

:: New game - initialise data
:: set start-state in STATE

SET example=exampledata

SET state=1000
GOTO :eof

:: Load game - including STATE

:S100.1
SET "state="
FOR /f "tokens=1*delims==" %%i IN (%savefile%) DO IF NOT defined %%i SET %%i=%%j

GOTO :eof

:: State 1000 - start game

:state1000

::  ** Just for a demo, show example as loaded from savefile

ECHO example=%example%

ECHO You see a shimmering blue-hued house with four doors numbered 1,2,3 and 4
SET "vr=1001 1 1002 2 1003 3 1004 4 1001 one 1002 two 1003 three 1004 four"
SET message=Which door do you choose
GOTO userio

:: State 1001 - door 1

:state1001
ECHO You see John Lodge
SET example=John Lodge
:: OK, from here, you're on your own. I'll force a state and loop
SET state=1000
GOTO :eof


:: State 1002 - door 2

:state1002
ECHO You see Graeme Edge
SET example=Graeme Edge
:: OK, from here, you're on your own. I'll force a state and loop
SET state=1000
GOTO :eof


:: State 1003 - door 3

:state1003
ECHO You see Justin Hayward
SET example=Justin Hayward
:: OK, from here, you're on your own. I'll force a state and loop
SET state=1000
GOTO :eof


:: State 1004 - door 4

:state1004
ECHO You see Ray Thomas
SET example=Ray Thomas
:: OK, from here, you're on your own. I'll force a state and loop
SET state=1000
GOTO :eof

With the above code, you can see a skeleton. :mainloop simply establishes a 'repeat until exitstructure, whereEXIT` is state=999999. I've used numbers for the states, but that's just a matter of choice.

For any particular state, you (optionally) do something, then set up a prompt message (don't call it prompt - that's a batch keyword) and a set of valid responses (vr is easier to type than valid_responses) then go to the :userio procedure (which returns to the :mainloop after accepting a response.

:userio saves the entire current environment (hence having an "autosave" feature) then prompts with the message and acepts a response. Set /p will leave response unchanged if enter is pushed, so setting response to [nothing] first will ensure that enter doesn't repeat the previous response.

I've chosen to replace any space characters entered with underscores - this makes processing easier as you don't have to worry about spaces in strings (it's not complete - commas, tabs and semicolons; redirectors and ampersand can also be problematic...)

Next, if the user enters EXIT or QUIT the exit state is assigned.

Otherwise, the valid-responses sting is matched to the response received. The vr string is simply

nextstate ifthisresponse nextstate ifthisresponse nextstate ifthisresponse nextstateotherwise

nextstateotherwise does not need to appear, and if it doesn't, an invalid response message is generated and the input re-requested.

So - from state 0, you're promted for your name, and the next state will be 100 regardless.

State100 sets savefile to the user's response (name) and if that file exists, any variable recorded on the savefile is reloaded into the environment, restoring the game to its exact state the last time the program was EXITed. If the file doesn't exist, then you have the opportunity to establish any game data you need - I've just set up a variable example as an - er, example.

State1000 starts the game. I've just shown the value of example for demo purposes. It should start out as exampledata as established in state100-no-savefile. So - you get a scenario-description, establish the prompt message and vr defines the next state to be 1001 if your response is (1 or one); 1002 for (2 or two)...

Choosing 1,2,3 or 4 switches you to the next state; the example string is changed, and - well, I've forced state1000 to be the destination. What you'd do is simply follow the bouncing ball in state1000.

Now - if you type exit, the program ends. Re-run and type the same username, and the value of example will be displayed as the last-established value, restored from the savefile.

As a little extension, you could add a help system - simply by adding in

IF /i %response%==help call :help&goto useriolp

after the FOR %%r IN (EXIT quit) ... line. Note that you can make the :help routine context-sensitive because you have the value of state to tell you where you are.

Equally, you could implement a look system, if you like, same principle.

All in batch. No need for other languages at all... :)