0

I am trying to create a Batch Game, where it has an inventory similiar to Skyrim, Oblivion, and other well known Games similiar. The ides is that there is not a fixed number of Inventory slots, but rather, the game creates a new slot if the existing slots are occupied. I already know how to make the game check for them, ish.

if '%item1%'=='blank' (set item1=%item%) else (if '%item1%'=='%item%' set /A item1qua=%item1qua%+1)
if '%item2%'=='blank' (set item2=%item%) else (if '%item2%'=='%item%' set /A item2qua=%item2qua%+1)

I also dont know how to create a batch script that changes the number each time until the inventory slot is found as blank. Then the Game has to save all the Inventory slots when done. My current method is this:

( Echo @echo off
  Echo set item1=%item1%
  Echo set item1qua=%item1qua%
  Echo set item2=%item2%
  Echo set item2qua=%item2qua%
  Echo set item3=%item3%
  Echo set item3qua=%item3qua%
  Echo set item4=%item4%
  Echo set item4qua=%item4qua%)>>%playername%.bat

The term "qua" simply refers to the Quantity. I have tried this code:

set num=1
:inv
if '%item%num%%'=='blank' (set %item%num%%=%item% && goto next) else (set /a num=%num%+1)
goto inv

In short, this would expand the inventory as the player gets more items. The items would have a weight, just like in Elder scrolls and other games, I want to add that sacred annoyance to players (hehe), however, I would also want the code to remove the extra 'blank' itemslots, without leaving a gap in the numbering system, example: item1, item2 item4, item7, item8

My previous method was to copy an existing .bat file with thw item data on form the mother folder, and place it in a folder elsewhere which the player could veiw their items using the dir command. As you can imagine, not very productive.

My second method was more in the Alpha stage of the game, when it was basically a life simulator, which sort of got abondoned, but left in the game folder just incase i picked it up again:

>>Users\%fname%.bat Echo set weed=%weed%
>>Users\%fname%.bat Echo set money=%money%
>>Users\%fname%.bat Echo set water=%water%
>>Users\%fname%.bat Echo set lighters=%lighters%
>>Users\%fname%.bat Echo set cigarettes=%cigarettes%
>>Users\%fname%.bat Echo set lightbulbs=%lightbulbs%

EDITS

Thanks to the link provided by Chris Schaller, I found a Code that could work, and edited to what I needed.


@echo off
set len=11
set obj[0]=Gold
set obj[1]=Silver
set obj[2]=Sword
set obj[3]=Knife
set obj[4]=Greenfelt
set obj[5]=Amulet
set obj[6]=Chickenleg
set obj[7]=Necklace
set obj[8]=StolenItem
set obj[9]=GoldIngot
set obj[10]=Statuette
set obj[11]=Seeds

set i=0
:loop
if /i %i% equ %len% goto :eof
for /f "usebackq delims== tokens=2" %%j in (`set obj[%i%]`) do (
    echo %%j
)
pause
set /a i=%i%+1
goto loop

The code works good for some aspects, however how would I allow obj[0] increase each time?

A.S.C

  • You seriously want to do all that as a batch script? You should use arrays to store the items, rather than individually naming each one. That way you can have a varying number of items with the same code, your current logic is actually dynamically executing and is not very scalable. – Chris Schaller Feb 23 '21 at 13:38
  • 1
    Theres lots of stuff out there, look at https://helloacm.com/how-to-use-array-in-windows-batch-programming/ for a simple example – Chris Schaller Feb 23 '21 at 13:39
  • @ChrisSchaller , Thank you, Ill make sure to check it out. Also, how do you mean by arrays? Will I find that on the link? – Alexander Savidge-Conway Feb 23 '21 at 14:11
  • @ChrisSchaller, I have tried the link, it does not seem that the batch script works ( the second example) – Alexander Savidge-Conway Feb 23 '21 at 14:19
  • Try this one then, I'm just trying to point you to articles that will help you research the concept: https://o7planning.org/11601/batch-array#:~:text=%20Arrays%20in%20Batch%20Scripting%20Language%20%201,A%20structure%20is%20an%20object%20with...%20More%20 – Chris Schaller Feb 23 '21 at 23:02

2 Answers2

0

The easiset way would be to have all variables that have to be saved starting with a special character (like #or @ or ~ or _ or ...) or string (like obj[ in your Edit). Saving them then is as easy as:

>Users\%fname%.sav set #

(or with the example in your Edit: >Users\%fname%.sav set obj[)

and to read them again with:

for /f "delims=" %%a in ("users\%fname%.sav") do set "%%a" 
Stephan
  • 53,940
  • 10
  • 58
  • 91
0

What your aiming to do is increment a count as new items are added to the inventory.

For this task type, I'd suggest using a function as inventory management is a highly repetative task in batch rpg games.

Functions in batch scripting are labels that are called with parameters repetative actions are performed upon.

In the context of game design for an RPG, you'll want to allow for use accross different situations, such as adding loot, purchases or rewards to inventory.

For a more complex game that supports a variety of items of a similar type, using itemtype arrays can makes things easier - Think menu tabs where you selcet weapons and get a list of just the weapons in your inventory.

Below is an example of how to approach scripting a function for adding items to inventory that tests 2 conditions are valid prior to adding the item - 1) The cost does not exceed funds, 2) The weight of the item does not push the total carry weight over the maximum.

itemweight and itemcost values default to 0 if no paramter is supplied when calling to allow items with no weight or that are found / given to be added to inventory.

@Echo off & Cls
 For /F "Tokens=1 Delims==" %%G in (' Set "#"  2^> nul ')Do Set "%%G="
 Set /A "#Money=100,Maxweight=25000,#weight=0"
::: redirect output of inventory to nul to suppress output of item added to inventory notifcation as desired
 For %%G in ("Healing Potion" "Old Key" "Map")DO Call :Inventory %%G Miscellaneous 10 >nul
 For %%G in ("Vambraces" "Boots of Luck" "Helm")DO Call :Inventory %%G Armor 1000 >nul
 Call :Inventory "Dagger" OneHandedWeapon 250 >nul
 Call :Inventory "Short sword" OneHandedWeapon 4000 >nul
 Call :Inventory "Katana" OneHandedWeapon 4750 > nul
 Set #
 Endlocal
Goto :Eof

:Inventory         <itemname> <itemtype> <itemweight> <itemcost>
::: Remove item:   <itemname> /R
::: undefines all array elements containing itemname in varname or value. Use unique and descriptive Item names.
 If /I "%~2" == "/R" (
  For /F "Tokens=1,2* Delims==" %%G in (' Set "#" 2^> nul ^|%__Appdir__%\findstr.exe /LIC:"%~1" ')Do Set "%%G="
  Goto :getweight
 )
 Set "Itemname=%~1"
 Set "Itemtype=%~2"
 If "%~4"=="" (Set "cost=0")Else (
  Set "cost=%~4"
  For /F %%G in ('Set /A #money-%~4')Do if %%G LSS 0 (
   Echo(You cannot afford %itemname%
   Goto :Eof
  )
 )
 If "%~3" == "" (Set "itemweight=0")Else (
  Set "itemweight=%~3"
  For /F %%G in ('Set /A maxweight-%~3-#weight')Do if %%G LSS 0 (
   Echo/You are carrying too much.
   Goto :Eof
  )
 )
 Set /A "#money-=cost"
 Set "#%itemname%[grams]=%itemweight%"
 Set /A #Inv{i}+=1+0
 Set "#Inventory[%#Inv{i}%]=%itemname%"
 If Defined Itemtype (
  Set /A #%ItemType%{i}+=1+0
  Call Set "#%ItemType%[%%#%ItemType%{i}%%]=%itemname%"
 )
 Echo(%~1 added to Inventory.
:getweight
::: Updates the current weight of all inventory items by summing all itemname[grams] definitions
 Set "#weight=0"
 For /F "Tokens=2 Delims==" %%G in (' Set "#" ^| Findstr /LIC:"[grams]"')Do Set /A #weight+=%%G
Goto :Eof

Note: The above is intended to example a method for adding items to inventory after assessing if they Can / should be added. The itemname /R 'remove item' component of the function is a minimal example of undefining an element from the inventory array/s however this approach does not shift array variable indexes to fill the gap left by the undefined variable - Something to be mindful of if you were to loop through the array using a for /L loop.

The below is an example of Incorporating a character login and save system that takes advantage of the use of # perfixed variables.

::: AUTHOR: T3RRY Created: 06/03/2021 Version: 1.3 Filename: RPGInventorySystem
:# Purpose:  Provide an easy to use, ready to go Template for creating Batch RPG Games
:# Features:
:# - :Login Function 
:#   - remembers last played character; offers single key login for that character.
:#   - flags if character is New or Returning
:# - :Getin Input function to restrict and validate player Input
:# - Example Template of Creating Classes with Starting Inventory { :Knight function }
:# - Multipurpose :Inventory Funtion That Saves Inventory changes Immediately
:# - :ManageInventory Function to allow players to well... manage their inventory.
:# - Menu Macro for easy menus.

@Echo off & Goto Prep
=======================================================================:# FUNCTIONS
:# Inventory Arguments and Usage Info:
:# Arg order Mandatory

======================:# ADDING ITEMS TO INVENTORY: Initial Inventory; Loot; Gifts / Rewards; Purchases
:Inventory              <ItemName> <ItemType> <ItemSubType> <ItemWeight> <ItemCost> {Optional:"ModifierType=Value"} {Optional:/F}
::::::::::::::::::::::::::::::::::::::::::::::::::
:# Optional Arg "/F": Must be last Arg; Flags the Item as free; Does not Subtract ItemCost from Players #Money
:#  Allows Items to be Looted / Gifted / Rewarded that have value stored for use when Selling Items. See Below
======================:# REMOVING / SELLING ITEMS:
:# Remove item:         <ItemName> /R <ItemSubType>
:#  Optional third Arg is used when selling an Item. May be a Sum, Integer Value or use Array: !#ItemName.Value!
:#  /R - Undefines all array elements containing ItemName in varname or value. Use unique and descriptive Item names.
:::::::::::::::::::::::::::::::::::::::::::::::::::
:# Sell item:           <ItemName> /R <ItemSubType> <ItemSaleValue>
======================:# EQUIPPING ITEMS:
:# Equip an item   :    <Itemname> /E <ItemSubtype>
======================:# CHECKPOINTS:
:# Save a Checkpoint:   <LabelName> /L
:::::::::::::::::::::::::::::::::::::::::::::::::::
:# IMPORTANT - RESERVED VARIABLES - The above Parameter names; #%1.Grams #%1.Value #Display.Weight #%3{i} #Weight List? Count
:#  - Arrays:         #%ItemName%.Grams #%ItemName%.Value #Equipped.%ItemSubType%
:#  - Lists:          #Inventory.Types #Inventory.%ItemType% #Inventory.%ItemType%.%ItemSubType%
:# RECOMMENDATION: Use a selection of Category names for ItemTypes that will be Equipped.
:# - Only one of Each ItemSubType may be Equipped at A time.
:#  - It is appropriate that only 1 pair of Boots may be worn, but multiple pieces of different Armor may be equipped:
:#  - Instead of just Defining all armors to the ItemType Armor:
:#  - Define Type Armor and Subtypes: Helm Mantle Gloves Vambraces Pauldrons Boots Pants
:# DEPENDENCIES - Defined in ':Login': #Name Game.Save
 If /I "%~2" == "/L" (
  Set "#Location=%~1"
  Goto :Save
 )

:# Removes or Sell ItemName From Inventory;  Removes ItemName From ItemSubtype List
 If /I "%~2" == "/R" (
  Set "Value="
  If not "%~5" == "" Set "Value=%~5"
  For /F "Tokens=1,2* Delims==" %%G in (' Set "#" 2^> nul ^|%__Appdir__%findstr.exe /LIC:"%~1" ')Do (
rem /* Test if Variable is a List Variable; If Not Undefines Variable */
   Set "List?=%%G"
   If not "!List?:~0,10!" == "#Inventory" (
    Set "%%G="
   )Else (
rem /* If Variable is a List Variable; Remove ItemName from ItemSubType List */
    Set "%%G=!%%G: "%~1"=!"
Rem /* If ItemSubType List is Empty; Remove ItemSubtype from ItemType List */
    If "!%%G!" == "" (Set "#Inventory.%~3=!#Inventory.%~3: "%~4"=!")
   )
  )
rem /* If Item SaleValue provided; Increment #Money by Value */
  Set /A "#Money+=!Value!+0"
  Goto :Save
 )


:# Build Itemtype Arrays and List Using Parameters
 Set "ItemName=%~1"
 Set "ItemType=%~2"
 Set "ItemSubtype=%~3"
 Set "Count=0"
:# Limit ItemTypes to 36 max supported by Menu macro
 If Not "!#Inventory.%ItemType%!" == "" (
  For %%G in (!#Inventory.%ItemType%!)Do Set /A "Count+=1"
  If !Count! GTR 36 (
   Echo(You own too many types of %ItemType%. !ItemName! cannot be Acquired.
   Exit /B 3
  )
 )
 Set "Count=0"
:# Limit Subtypes to 36 max supported by Menu macro
 If Not "!#Inventory.%ItemType%.%ItemSubType%!" == "" (
  For %%G in (!#Inventory.%ItemType%.%ItemSubType%!)Do Set /A "Count+=1"
  If !Count! GTR 36 (
   Echo(You own too many types of %ItemSubtype%. !ItemName! cannot be Acquired.
   Exit /B 3
  )
 )
 If "%~4" == "" (Set "ItemWeight=0")Else (
  Set "ItemWeight=%~4"
  For /F %%G in ('Set /A #MaxWeight-%~4-#weight')Do if %%G LSS 0 (
   Echo/You are carrying too much.
   Exit /B 2
 ))
:# Determine Value of Item and If item is To be Free or Paid For
 Set "Free.Item="
 Echo(%*|%__APPDIR__%findstr.exe /LIC:"/F" > Nul && Set "Free.Item=Y"
 If "%~5"=="" (Set "ItemCost=0")Else (
  Set "ItemCost=%~5"
  If Not Defined Free.Item (
   For /F %%G in ('Set /A #money-%~5')Do if %%G LSS 0 (
    Echo(You cannot afford %ItemName%
    Exit /B 1
   )
  )
 )
:# Define a Modifier To ItemName.modname For Items With Stat Modifiers If supplied
 If not "%~6" == "" If /I not "%~6" == "/F" (
  Set "#%ItemName%.%~6" 2> Nul || (
   Echo(Invalid Argument "[%~6]" In %*
   Echo(Required: "ModifierType=Value"
   Timeout /T 3 /NoBreak
   Pause
   Endlocal & Goto :Eof
  )
 )
:# Define #ItemName Arrays for Grams and Value
 Set "#%ItemName%.Grams=%Itemweight%"
 Set "#%ItemName%.Value=%ItemCost%"
 Echo(!ItemName! added to Inventory.
:# Search savefile for Itemtype; Itemsubtype; and Itemname; Append to relevant list if not present
 %__APPDIR__%findstr.exe /LIC:"!ItemType!" "%Game.Save%" > nul 2> nul || Set "#Inventory.Types=!#Inventory.Types! "!ItemType!""
 %__APPDIR__%findstr.exe /LIC:"!ItemSubType!" "%Game.Save%" > nul 2> nul || Set "#Inventory.%ItemType%=!#Inventory.%ItemType%! "!ItemSubType!""
 %__APPDIR__%findstr.exe /LIC:"!ItemName!" "%Game.Save%" > nul 2> nul || Set "#Inventory.%ItemType%.%ItemSubType%=!#Inventory.%ItemType%.%ItemSubType%! "!ItemName!""

=================================================
:Save
:# Remove Item Categories from #Inventory.Types list when all Category sub items are sold / dropped.
 For %%G in (!#Inventory.Types!)Do If "!#Inventory.%%~G!" == "" Set "#Inventory.Types=!#Inventory.Types: "%%~G"=!"
 Set /A "#Def=#Dmg=#weight=0"
:# Updates the below Modifiers of all equipped inventory items by summing all ItemName.%%M definitions
 For %%M in (DEF DMG)Do For /F "Tokens=1,2* Delims==" %%G in ('Set "#Equipped" 2^> nul')Do (
  For /F "Tokens=2 Delims==" %%i in ('Set "#%%H"^|%__APPDIR__%Findstr.exe /LIC:".%%M"')Do (
   Set /A "#%%M+=%%i+0"
  )
 )
:# Updates the current weight of all inventory items by summing all ItemName.Grams definitions
 For /F "Tokens=2 Delims==" %%G in (' Set "#" ^| Findstr /LIC:".Grams"')Do Set /A #weight+=%%G
 Set "#Display.weight=%#weight:~0,-3%.%#weight:~-3%"
:# Enact Save for # prefixed variables
:# Saves Game Variables prefixed by # to Game.Save cmd file to be called on Login
 (For /F "tokens=1,2* Delims==" %%G in ('Set "#"')Do Echo(Set "%%G=%%H") >"%Game.Save%"
 Echo(%#Name%>"%~f0:Last_Char"
 Exit /B 0

=================================================
:ManageInventory {Optional:/E /S /D}
:# Control Available Inventory options by Calling ManageInventory with the Options you wish
:# to allow according to the current Gamestate.
 Set "MI.Options="
 If not "%~1" == "" Echo/%*|Findstr /LIC:"E" > Nul && Set "MI.Options=!MI.Options! Equip"
 If not "%~1" == "" Echo/%*|Findstr /LIC:"S" > Nul && Set "MI.Options=!MI.Options! Sell"
 If not "%~1" == "" Echo/%*|Findstr /LIC:"D" > Nul && Set "MI.Options=!MI.Options! Drop"
:# /R - Removes the Sell option from Invetory Action
:# RESERVED VARIABLES - Type; SubType; Action; All Menu Macro Reserved Variables
:# DEPENDENCIES -Functions: Inventory; Save -Macro: Menu -Variables: #Money #Equipped
:#                          Inventory Function Defines Lists used with Each Submenu.
:# This function returns no Errorlevels.
CLS
 Echo(         Credit: !#Money! Damage: !#Dmg! Defence: !#Def! Burden: !#Display.Weight! kg /!#MaxWeight:~0,-3!.!#MaxWeight:~-3! kg.
 Echo( Equipped Items:
 (Set "#Equipped" 2> nul > nul ) || Echo( No items equipped.
 (For /F "Delims=" %%# in ('Set #Equipped 2^> nul') Do For /F "Tokens=1,2 Delims==" %%C in ("%%#")Do (
  Set "[item]=%%C"
  Set "[item]=![item]:*.=!"
  Set "[item]=![item]:.=: !"
  <nul set /P "=> ![item]! = %%D!LF!"
 )) 2> nul

:# Choose Action Type or Exit ManageInventory Function; Each Submenu can abort to this Primary Menu
 %Menu% Exit !MI.Options!
 CLS
 Set "Action=!Option!"
 Echo(Select Inventory Category:
 %Menu% Return !#Inventory.Types!
 If "!Option!" == "Return" (Goto :ManageInventory)Else CLS
 Set "Type=!Option!"
 Echo(Select a type of !Type! to !Action!:
 %Menu% Return !#Inventory.%Type%!
 If "!Option!" == "Return" (Goto :ManageInventory)Else CLS
 Set "SubType=%Option%"
:# Apply action type to selected ItemName
:# If Equipping; Handle Two Handed / [One Handed/Off Hand] Equipment Conflict
 Echo(Selecting a !Subtype! from your !Type! Will !Action! it. Return [0] To cancel.
 %Menu% Return !#Inventory.%Type%.%SubType%!
 If Not "!Option!" == "Return" (
  If "!Action!" == "Equip" (
   Set "#Equipped.%Type%.%Subtype%=%Option%"
   If /I "%SubType%" == "Two Handed" (Set "#Equipped.Weapons.One Handed="&Set "#Equipped.Weapons.Off Hand=")
   If /I "%SubType%" == "One Handed" (Set "#Equipped.Weapons.Two Handed=")
   If /I "%SubType%" == "Off Hand" (Set "#Equipped.Weapons.Two Handed=")
   Call :Save
  )
  If "!Action!" == "Sell" (
   Echo(Sell Value: $!#%Option%.Value!. Confirm [Y/N]
   For /F "Delims=" %%O in ('Choice /N /C:YN')Do If %%O==Y Call :Inventory "%Option%" /R "!Type!" "!SubType!" "!#%Option%.Value!"
  )
  If "!Action!" == "Drop" Call :Inventory "%Option%" /R "!Type!" "!SubType!"
 )
Goto :ManageInventory

=================================================
:login
:# clear any preexisting definitions
 (For /F "tokens=1,2* Delims==" %%G in ('Set "#"')Do Set "%%G=") 2> nul

:# check Alternate data stream 'Last_Char' of this file; offer single key login for last played character.
 more < "%~f0:Last_Char" 2>nul >nul && For /F "Delims=" %%G in ('more ^< "%~f0:Last_Char"')Do (
  Echo(Continue as %%G Y/N
  For /F "Delims=" %%C in ('Choice /N /C:YN')Do if "%%C"=="Y" (
   Set "Game.Save=%TEMP%\%~n0_%%G_Save.cmd"
   CALL "%TEMP%\%~n0_%%G_Save.cmd"
   Exit /B 0
  )
 )
 (For /F "tokens=1,2* Delims==" %%G in ('Set "#"')Do Set "%%G=") 2> nul
:# Login Errorlevels: [2:User quit during Login.] [1:New Character] [0:Existing Character]
:# IMPORTANT - RESERVED VARIABLES:
:# - #Name #Pass Verify
:#   #Name used to create a .cmd file that is called when the user logs back in to the character to reassign
:#   # prefixed variables.
CLS
 Echo(Existing Characters:
 (Dir /B "%TEMP%\%~n0_*_Save.cmd" > Nul 2> nul || Echo(None. )
 For /F "Tokens=2 Delims=_" %%G in (' Dir /B "%TEMP%\%~n0_*_Save.cmd" 2^> nul ')Do Echo(%%G
rem /* example definitions */
 Call :GetIn #Name "[a-zA-Z ]*" /C /S /P:Enter your characters name
 If Not "%Errorlevel%" == "0" Goto :login
 Call :GetIn #Pass "[0-9][0-9][0-9][0-9]" /S /P:Enter your four Digit Pin
 If Not "%Errorlevel%" == "0" Goto :login
 Set "Verify=%#Pass%"
 Set "Game.Save=%TEMP%\%~n0_%#Name%_Save.cmd"
rem /* load saved values */
 If Exist "%Game.Save%" Call "%Game.Save%"
 If /I not "%Verify%" == "%#Pass%" (
  Echo(Invalid Password
  %Menu% Exit Retry
rem /* Flag quit program */
  Goto :Login
 )
rem /* offer delete/ login if exists */
 If Exist "%Game.Save%" (
rem /* Flag Existing Character Errorlevel 0 */
  %Menu% "Remove Character" "Continue"
  If /I "!Option!"=="Continue" Exit /b 0
  %Menu% "Abort" "Proceed"
  If /I "!Option!"=="Abort" Goto :Login
  Del "%Game.Save%"
  Goto :Login
 ) Else (
rem /* Flag New Character Errorlevel 1 */
  Exit /B 1
 )
=====================================================

:strlen <resultVar> <stringVar>
(   
    setlocal EnableDelayedExpansion
    (set^ tmp=!%~2!)
    if defined tmp (
        set "len=1"
        for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
            if "!tmp:~%%P,1!" NEQ "" ( 
                set /a "len+=%%P"
                set "tmp=!tmp:~%%P!"
            )
        )
    ) ELSE (
        set len=0
    )
)
( 
    endlocal
    set "%~1=%len%"
    exit /b
)
=====================================================

:GetIn [ReturnVar] ["qouted findstr search pattern"]  [Optional:"/C" - required for patterns with spaces] [Optional "/S" - Suppress input accepted] [/P:Custom Prompt]
:# Input validation function for restricting input to desired character classes or [limited] Regex Patterns.
:# -IMPORTANT - RESERVED VARIABLES: InputParams /C /P /S rVar Pattern Exit.Code
:# - GetIn Errorlevels: 
:#  - Errorlevel 3 - User has failed to provide valid input * OR * regex pattern is
:#    invalid * OR * GetIn is a called label in a file that has recieved input
:#    from a pipe that has not been handeled before the call.
:#  - Errorlevel 2 - GetIn is a script that has been invoked by a pipe
:#  - Errorlevel 1 - GetIn has been called without Arg 2 for Regex Pattern
:#  - Errorlevel 0 - Input has been assigned that matches the Regex Pattern
:# GetIn Usage Examples - Description is replaced with Arg 1-ReturnVar:
:#  Call :GetIn Pin "[0-9][0-9][0-9][0-9]" /S /P:Enter a four Digit Pin Number
:#  Call :GetIn Alphanumeric-String "[0-9a-zA-Z]*"
:#  Call :GetIn semicolon-delimited-hexadecimal-String "[0-9a-fA-F][0-9a-fA-F][:][0-9a-fA-F][0-9a-fA-F]"
:#  Call :GetIn AlphaString-with-3-Digit-Numeric-suffix "[a-zA-Z]*[0-9][0-9][0-9]"
:#  Call :GetIn list-of-delimited-words "[a-zA-Z, ]*" /C
:#  Call :GetIn pair-of-delimited-numbers "[0-9]*[, ][0-9]*" /C

 SETLOCAL EnableExtensions EnableDelayedExpansion
 Set "/C=" & Set "/P=" & Set "/S="
 Set InputParams=%*
 If Not "!InputParams:/C=!" == "!InputParams!" Set "/C=_"
 If Not "!InputParams:/S=!" == "!InputParams!" Set "/S=_"
 If Not "!InputParams:/P=!" == "!InputParams!" (
  Set "/P=!InputParams:*/P:=!"
  Set "/P=!/P:"=!"
 )
rem [ test if standalone script - if so test if accessed by pipe; reject execution if true ]
 If "%~0" == "%~n0" For %%G in (!cmdcmdline!)Do Echo/%%~G|Findstr.exe /LIC:"/S" > nul 2> nul && (Set "Exit.Code=2" & Goto :Getin.Err)

:GetInRetry
 Del /Q "%TEMP%\%~n0_validate.~tmp" 2> nul
 If !Exit.Code! GTR 5 Goto :Getin.Err
 Set "rVar="
 If "%~2" == "" GOTO :Getin.Err
 Setlocal DISABLEdelayedExpansion & rem ::: display occurances of carets [^] in pattern
 Endlocal & Set "Pattern=%~2"
 If Not Defined /P (
  Set /P "rVar=Input Format for %1:!LF!!Pattern!!LF!!LF!Enter %1: "
 )Else  Set /P "rVar=!/P!: "
 If "!rVar!" == "" (Set /A "Exit.Code+=1" & <nul Set /P"= ^! Invalid value.!LF!" & Goto :GetInRetry)
 > "%TEMP%\%~n0_validate.~tmp" (Echo/!rVar!)
 If Defined /C (
  Type "%TEMP%\%~n0_validate.~tmp" | %__APPDIR__%findstr.exe /RXC:"%~2" >nul || (Set /A "Exit.Code+=1" & <nul Set /P"= ^! Invalid value. !LF!" & Goto :GetInRetry)
 ) Else (
  Type "%TEMP%\%~n0_validate.~tmp" | %__APPDIR__%findstr.exe /RX "^%~2$" >nul || (Set /A "Exit.Code+=1" & <nul Set /P"=- ^! Invalid value. !LF!" & Goto :GetInRetry)
 )
 If not defined /S Echo/%1: [!rVar!] Accepted
 ENDLOCAL & Set "%~1=%rVar%"
 Del /Q "%TEMP%\%~n0_validate.~tmp"
 Exit /B 0
:GetIn.Err
Exit /B %Exit.Code%

===========================:# DEFINE INITIAL INVENTORY - EXAMPLE Only
:Knight Starter Pack
:# Example of defining initial variables for a new character prior to commencing gameplay
:# IMPORTANT - Inventory function is Dependant on #Money #MaxWeight and #Weight variables.
 Set /A "#Money=500,#MaxWeight=25000,#Weight=0"
:# suppress output of Inventory added notifcation by redirecting to nul as desired.
 Call :Inventory "Dagger" Weapons "Off Hand" 250 50 "DMG=5" /F > nul
 Call :Inventory "Buckler" Weapons "Off Hand" 400 40 "DEF=6" /F > nul
 Call :Inventory "Short sword" Weapons "One Handed" 4000 250 "DMG=10" /F > nul
 Call :Inventory "Twin Bladed Katana" Weapons "Two Handed" 5500 350 "DMG=12" /F > nul
 Call :Inventory "Leather Cap" Armor Helm 500 25 "DEF=3" /F > nul
 Call :Inventory "Faded Map" Miscellaneous Maps 20 "DEF=5" /F > nul
 Call :Inventory "Healing Potion" Potions Restorative 10 25 "Heal=30" /F > nul
 Call :Inventory "Old Key" Miscellaneous Keys 10 1 /F > nul
 Call :Inventory "Worn Leather Vambraces" Armor Vambraces 1000 15 "DEF=2" /F > nul
 Call :Inventory "Boots of Luck" Armor Boots 1500 50 "DEF=4" /F > nul
Goto :Eof
===========================:# END OF FUNCTIONS

:Prep
=====================================================:# MACRO DEFINITIONS
===================================:# MENU macro prep and Definition :::
:# IMPORTANT - RESERVED VARIABLES:
:# - LF \N Game.Save
(Set LF=^

%= Linefeed var used for multi-line output in GetIn macro - Do not modify. =%)
(Set \n=^^^

%= Newline var \n for multi-line macro definition - Do not modify. =%)

:# Enable environment for macro expansion, Arrays and code block variable operations
 Setlocal EnableExtensions EnableDelayedExpansion
==================================================================
:# Menu macro escaped for Definition with DelayedExpansion Enabled
:# IMPORTANT - RESERVED VARIABLES: Menu CH# CHCS Options Option Opt[i] Option.Output Cholist DIV
:# Key index list Allows 36 menu options. Component of Menu Macro
 Set "ChoList=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
rem /* Get console width for dividing line. */
 for /F "usebackq tokens=2* delims=: " %%W in (`mode con ^| %__APPDIR__%findstr.exe /LIC:"Columns"`) do Set /A "Console_Width=%%W"
:# Build dividing line for menu output.
 Set "DIV="&For /L %%i in (2 1 %Console_Width%)Do Set "DIV=!DIV!-"
:# Menu macro Usage: %Menu% "quoted" "list of" "options"
==== Set Menu=For %%n in (1 2)Do if %%n==2 (%\n%
%= Output Dividing Line                 =%  Echo(^^!DIV^^!%\n%
%= Reset CH# index value for Opt[#]     =%  Set "CH#=0"%\n%
%= Undefine choice option key list      =%  Set "CHCS="%\n%
%= For Each in list;                    =%  For %%G in (^^!Options^^!)Do (%\n%
%= For Option Index value               =%   For %%i in (^^!CH#^^!)Do (%\n%
%= Build the Choice key list and Opt[#] =%    Set "CHCS=^!CHCS^!^!ChoList:~%%i,1^!"%\n%
%= array using the character at the     =%    Set "Opt[^!ChoList:~%%i,1^!]=%%~G"%\n%
%= current substring index.             =%    Set "option.output=%%~G"%\n%
%= Display ; removing # variable prefix =%    Echo([^^!ChoList:~%%i,1^^!] ^^!Option.output:#=^^!%\n%
%= Increment Opt[#] Index var 'CH#'     =%    Set /A "CH#+=1"%\n%
%= Close CH# loop                       =%   )%\n%
%= Close Options loop                   =%  )%\n%
%= Output Dividing Line                 =%  Echo(^^!DIV^^!%\n%
%= Select option by character index     =%  For /F "Delims=" %%o in ('Choice /N /C:^^!CHCS^^!')Do (%\n%
%= Assign return var 'OPTION' with the  =%   Set "Option=^!Opt[%%o]^!"%\n%
%= value selected from Opt[CH#] array.  =%   If /I "^!Option^!" == "Exit" Exit /B 2%\n%
%= Return to previous script on Exit    =%  )%\n%
%= Capture Macro input - Options List   =% )Else Set Options=
========================================== ::: End Menu Definition

:StartGame
:# Make the Session Local
 Setlocal
==========================================:# MAIN GAME SCRIPT [ EXAMPLE ]
:# To Create / Continue a Character; Call Login. Errorlevel 0 = Returning Character
:# Modify The reponse to Errorlevel 1 [New Character] As you Wish to facilitate Creation of Character Classes.
:# Suggested: Use the Menu Macro with a list of Character Classes corresponding to functions and Call the selected class Label (IE - Call :Rogue)
 Call :Login
 If Errorlevel 2 Goto :Eof
 If Errorlevel 1 (
  Echo(Select your Class:
  %Menu% Exit "Knight" "Rogue"
  Call :!Option! 2>nul || (
   Echo(The !Option! Class has not been created yet. Use the example of the :Knight function to create your own Classes.
   Timeout /T 3 /NoBreak > Nul
   Pause
   Endlocal
   Goto :StartGame
  )
 )
:# Use Labels as checkpoints by Defining them to the Variable #Location
 If Errorlevel 0 If Defined #Location (Goto :!#Location!)
:# To [S]ell [E]quip or [D]rop Inventory:
:# If the Player is not in a Town / Shop; Use: Call :ManageInventory /ED to Lock out Sale of Items
 Call :ManageInventory /ESD

:Home This and below Label locations are examples of using Label Checkpoints
 CLS
 Call :Inventory Home /L
:# Use last selected option to prevent recursive calls.
 If not "!Option!" == "Home" (
  %Menu% Exit "Manage Inventory" "Travel"
 )Else %Menu% Exit "Manage Inventory"
 If "!Option!" == "Manage Inventory" (
  Call :!Option: =! /ESD
  Goto :Home
 )
 If not "!Option!" == "Travel" Goto :Eof

:Travel
 CLS
 Call :Inventory Travel /L
 Echo(Choose a Direction:
 %Menu% Exit Home East West North South
 Call :!Option: =! 2> Nul || If not Errorlevel 2 (
  Echo That Direction has not been Scripted yet. You'll have to make your own Adventure.
  Pause
 )
 Goto :Travel
T3RR0R
  • 2,747
  • 3
  • 10
  • 25