1

I'm working on an inventory management system in a batch RPG. In this test where an item is supposed to be transferred to the inventory, it's supposed to allow for duplicates to be stored in the next slots, so that if one slot is taken, it should be the next slot that's filled.

:test
cls
set /a newitm=%random% %%1 +1
echo You received a new item!
if %newitm%==1 set giveitm=Red Spotted Mushroom
if %newitm%==2 set giveitm=Key to Nowhere
if %newitm%==3 set giveitm=Key to Somewhere
if %newitm%==4 set giveitm=Nordic Berserker Helmet
if %newitm%==5 set giveitm=Blue Orchid
echo %giveitm% has been added to inventory.
pause
if "%giveitm%"=="Red Spotted Mushroom" goto newplant
if "%giveitm%"=="Blue Orchid" goto newplant
if "%giveitm%"=="Key to Nowhere" goto newkey
if "%giveitm%"=="Key to Somewhere" goto newkey
if "%giveitm%"=="Nordic Berserker Helmet" goto newarmor
goto test
:newplant
if %pcitmplant1%==none goto newplant1
if %pcitmplant2%==none goto newplant2
:newplant1
set pcitmplant1=%giveitm%
goto inventory
:newplant2
set pcitmplant2=%giveitm%
goto inventory

Here I'm testing a specific plant. Every time I run this part of the code twice in order to get two mushrooms, the window closes before taking me to the inventory screen. (The inventory screen itself is only supposed to display the variables like %pcitmplant1% through %pcitmplant10%.)

  • `%%1` is Modulo 1, which gives you a number between zero and zero. Add one and you always get `1`. If you have 5 items, you need Modulo 5 (a number between zero and 4) (plus 1 to get a number between 1 and 5) – Stephan Jul 26 '19 at 17:07
  • An undefined variable "empty", not `none`. `if` with an empty variable gives you a syntax error [see here for explanation](https://stackoverflow.com/a/27489844/2152082). You better use `if not defined pcitmplant1` – Stephan Jul 26 '19 at 17:10
  • Fro troubleshooting, don't run your script with a mouse click, but open a command prompt window and start it manually from there to be able to read any errormessages. – Stephan Jul 26 '19 at 17:11
  • To answer some questions: I disabled the randomizer to generate anything but the first option for testing, and I actually set any empty variables to "none" by default. – Joseph Massingill Jul 26 '19 at 17:20
  • Disabling the randomizer for troubleshooting is a valid and good approach (maybe you should have mentioned it). I suspect a syntax error (probably with an `if` statement. Maybe you forgot to set a variable to `none`? What's your error message? Does `set pcitmplant` show all of your variables? – Stephan Jul 26 '19 at 17:32
  • It seems to crash before :newplant1, because if I put a pause after it, it doesn't get that far. There's no error message, but the program closes immediately upon getting there. – Joseph Massingill Jul 26 '19 at 18:51
  • Using extra quotation marks everywhere possible, the program works fine, but all in-game references to items are surrounded in quotes. – Joseph Massingill Jul 26 '19 at 19:05
  • A batch file won't "crash" for no reason. I told you to execute it from an open cmd window to see the error messages. I suspect the reason is like this [possible duplicate](https://stackoverflow.com/questions/48282362/batch-cmd-exits-as-i-enter-the-input-with-space) – Stephan Jul 26 '19 at 19:47
  • Since your item names contain spaces, your code executes on the second allotment (eg) `if Red Spotted Mushroom==none goto newplant1` . This is a syntax error since the comparator (in this case `==`) does not directly follow the string after `if`. To make such a comparison, yo need to `"quote each side"` ie. `if "%pcitmplant1%"=="none" goto newplant1`. Two other items: It's easier in batch to assign strings using the syntax `set "var=value"` and not allow quotes in the value assigned. And second, `set "var="` sets `var` to *nothing* which can be detected easily with `if [not]defined var` – Magoo Jul 26 '19 at 23:17
  • Also, matching strings as you are doing is subject to tyops. Better to set a batch-array using `set "itemdesc[31]=Red Spotted Mushroom" - that way, `itemdesc[31]` is only ever defined once, and doesn't need to be repeated throughout your code. – Magoo Jul 26 '19 at 23:22

1 Answers1

0

You have a modulo bias in your code which should be addressed (See Here: https://stackoverflow.com/a/46991999/3985011 ) But that is not "game-breaking" per-se, but usually you would want to have an unbiased chance of something and control it by adding your own weighting.

Also, since you have static Items you want to assign, you could create Variables with IDs for each of them to make this process a little better.

I really love the Idea of Creating a game in CMD, if you would like to Collaborate Further I woudl love to trade code back ad forth.

I did this for a few hours of fun while between other work, Let's take some time to chat over thins as it's a bit much to write up everything so if you like the code let me know what portions you woudl like to know more about.

Here is your code re-written to make use of a basic inventory system, and to remove the Modulo bias.

@(
  SETLOCAL EnableDelayedExpansion
  ECHO OFF

  SET "_PCInv_Plant.Slots=11"
  SET "_PCInv_Armor.Slots=13"
  SET "_PCInv_Key.Slots=42"

  SET "ECHO_RW=Call :Echo_Color CF "
  SET "ECHO_GB=Call :Echo_Color 20 "
  SET "ECHO_AB=Call :Echo_Color B0 "
  SET "ECHO_LY=Call :Echo_Color 1E "
  SET "ECHO_YL=Call :Echo_Color E1 "
  SET "ECHO_YR=Call :Echo_Color EC "
  SET "ECHO_YB=Call :Echo_Color E0 "
  SET "ECHO_RY=Call :Echo_Color CE "
  SET "ECHO_BY=Call :Echo_Color 1E "

  SET "_Pad=000"

  SET "_eLvl=0"
)

CALL :Main

(
  Endlocal
  COLOR
  EXIT /B %eLvl%
)

:Echo_Color
  ECHO.>"%~2"
  FINDStr /A:%~1 /I ".*" "%~2" NUL
  DEL /F /Q "%~2" >nul 2>nul
GOTO :EOF

:Main

  CALL :Initialize_Inventory_Items

  REM Lets Get 5 Random Items added to the Inevntory from the shop by calling the Test Function 5 times
  COLOR 1E
  CLS
  ECHO.
  FOR /L %%L IN (1,1,5) DO ( 
    CALL :Test
  )
  CLS
  COLOR 0E
  ECHO.
  SET "_PCInv_"
  ECHO.
  %ECHO_AB% "============================================="
  %ECHO_AB% "== Results of Player Inventory Shown Above =="
  %ECHO_AB% "============================================="
  Pause
GOTO :EOF



:Test
  REM cls
  CALL :Random _# %_InvItem.count%
  REM ECHO. # %_#%
  ECHO.

  FOR /F "Tokens=1-2* Delims==" %%A IN ('
    SET "_InvItem_!_#!"
  ') DO (
    SET "_TType=%%B"
    SET "_TDesc=%%C"
  )

  ECHO(
  ECHO(
  %ECHO_AB% "You Recievded a !_TType!, It appears to be a '!_TDesc!'"

  REM SET Default Value = 0
  SET "_TSlot=0"

  REM Find First Inventory Slot available.
  FOR /F "Tokens=3 Delims=_=" %%A IN ('
    SET "_PCInv_!_TType!" ^| FIND /I /V "NONE"
  ') DO ('
    SET /A "_TSlot+=1"
  ) 2>NUL

  REM Place into the First Inventory Slot available.
  IF /I !_TSlot! GTR !_PCInv_%_TType%.Slots! (
    COLOR CE
    ECHO.No Room!
  ) ELSE (
    SET "_Tmp#=%_Pad%!_TSlot!"
    SET "_Tmp#=!_Tmp#:~-2!"
    REM Add The Item to the Inventory Slot.
    SET "_PCInv_!_TType!_!_Tmp#!=!_TDesc!"
    %ECHO_YB% " == The !_TType! has been added to Your inventory"
    PAUSE
  )


GOTO :EOF

:Random
  SETLOCAL DisableDelayedExpansion
  REM Loops until a valid result is obtained.

  SET /A "_Rnd=%Random%"
  SET /A "_Max_Valid=( 32767 - ( ( ( 32767 %% %~2 ) + 1 ) %% %~2 ) )"
  REM ECHO. "_Rnd" = "%_Rnd%"
  REM ECHO. "_Max_Valid" = "%_Max_Valid%"
  IF /I "%_Rnd%" GTR "%_Max_Valid%" (
    GOTO :Random
  )

  (
    ENDLOCAL
    SET /A "%~1=%_Rnd% %% %~2"
  )
  REM ECHO. # %_#%
GOTO :EOF


:Initialize_Inventory_Items

  REM Set up Inventory Items.
  SET "_InvItem_0=Plant=Red Spotted Mushroom"
  SET "_InvItem_1=Key=Key to Nowhere"
  SET "_InvItem_2=Key=Key to Somewhere"
  SET "_InvItem_3=Armor=Nordic Berserker Helmet"
  SET "_InvItem_4=Plant=Blue Orchid"

  REM  Store count of Inventory Items
  FOR /F %%A IN ('
    SET "_InvItem_"
  ') DO (
    CALL SET /A "_InvItem.count+=1"
  )

  REM Set all Player Inventory Slots to "None"
  FOR %%A IN (
    Plant
    Armor
    Key
  ) DO (
    REM ECHO _PCInv_%%A.Slots = !_PCInv_%%A.Slots!
    FOR /L %%L IN (1,1,!_PCInv_%%A.Slots!) DO (
      SET "_Tmp#=%_Pad%%%L"
      SET "_Tmp#=!_Tmp#:~-2!"
      REM ECHO SET "_PCInv_!_Tmp#!_%%L=None"
      SET "_PCInv_%%A_!_Tmp#!=None"
    )
  )

GOTO :EOF
Ben Personick
  • 3,074
  • 1
  • 22
  • 29