This simple application detects the user\'s home directory, detects how the operating system finds its way to the home directory, parses the INI file, and then increments the `level` entry for `player1` by 1. Save the file. Change to the `~/config` directory in a terminal, and then try running the application (it will fail, but that\'s intentional). $ lua ./main.lua lua: ./main.lua:4: module 'inifile' not found... This tells you that Lua attempted to use the `inifile` library, but couldn\'t locate it because the library is\'t installed on your system, it\'s installed in your project directory. Lua itself substitutes `?` with the *the name of the library you provide in `require` statements*. The end results of the commands are the same: you get the path to the library or libraries you need to add to the very top of your `main.lua` code: This simple statement sets `package.path` to be *whatever it already is*, and then appends (..) the `local` directory. It also replaces any instance of `?` with *whatever is being required*. ::: {.note} If you read other people\'s Lua code, you might see the alternate method of pointing Lua to a library. Sometimes, a programmer provides the path to the library manually in the `require` statement, using dots as delimiters: `require('lib.inifile.inifile')`. This isn\'t wrong or bad, but it is very specific to a *single* library file. Not all libraries consist of just one file, so that method is less flexible than providing the `package.path`. ::: Try your program again. This time, it is successful: $ lua ./main.lua slasher 7 zombie,vampire The file was parsed correctly. Now check the original `sample.ini` file to see if player1\'s level was updated. To see the contents of a file quickly in a terminal, you can use the `cat` command, which is short for *concatenate* (so you are, in effect, concatenating the file to nothing, so its contents are just printed to your terminal). $ cat ~/sample.ini [player1] name= slasher defeated = zombie,vampire level=8 [player2] name= vecna defeated = vampire,gug,shantak level=8 Lua has parsed, read, and written a plain text configuration using a local library. Deck building {#db-deck} ------------- Having completed the exercise in this chapter, you not only know how to store data on your user\'s computer, but you also know how to define data structures in a file to have it imported by your application. That means you don\'t have to define a deck of complex battle cards in the main code of your application, which means a smaller file for your executable code, and a lot less clutter in your main script. For the Blackjack game, the card deck was a simple 52 card poker deck. Your current project, Battlejack, can use a standard card deck, but part of the fun of programming digitally is that you can generate game assets without the costly manufacturing bills involved in creating a new deck of cards in the physical world. It doesn\'t make sense to limit the game to a standard poker deck when you can, instead, invent any theme you want for your game. Regardless of your artistic skill or access to artwork, 52 cards is a lot of cards to make. It\'s not impossible (there are over 10,000 Magic: The Gathering cards, and 2,000 in Magic Online) but for an independent game developer it\'s a tall order. When determining the assets for a game, it\'s important to look critically at what is necessary and what is just nice to have. For this project, even though the design assets were 52 cards, there were actually only 10 unique values: 1 through 10. For every iteration of cards 1 to 10, there were three cards worth 10 (Jack, King, Queen). Furthermore, although the dev deck had 4 suits, the suits actually had no effect on the game, so those can be thrown out. To create player identities, the alpha version of the game used red and black, and since that\'s easy and classic, the digital version can keep that. For accessibility, the digital version will also use a symbol along with the opposing colors, since not everyone can see the color red. To make the game a little more exciting, the digital version of Battlejack will enable players to \"level up\" as they continue to play. Levels in any game are a mix of rewards and, essentially, penalties; the players levels up and becomes more powerful, but only to face new challenges. That means the digital deck will have a small subset of extra cards that get shuffled into the game, throwing off the predictability of how often certain values get drawn, and a second subset of cards that serve as \"power ups\", granting the player a free bonus, anywhere from a +1 to +3, to their hand. There isn\'t much to this dataset, but it should be expressed separately from the user data because it is not data that is meant to change. It defines the virtual deck of cards, and that\'s all. Tracking which cards have been drawn during a game must be done by the application itself, because it gets reset every time a new game is started. Any permanent rewards or penalties or level data gets written to the user data file. Take a moment to think about what kind of deck you want to use for your Battlejack implementation, or download and use the deck provided with this book (the art is licensed under a Creative Commons license, so you may use the artwork for any purpose). Once you have decided on a theme, create a project folder called `battlejack`. Create `font` and `img` directories within your project folder, as usual. Create a deck definition file called `deck.ini` and save it into your project directory. You know that the card dealer library you made for Blackjack uses random numbers to select a card, so the key term in the definition file must be a number, meaning that the value must hold both the face and card value of the card. You can customize the definition file to suit your custom theme, or if you are using the art available with this book, you can use this: [card] 1 = mystic,1 2 = bard,2 3 = arcanist,3 4 = archer,4 5 = goblin,5 6 = construct,6 7 = cavalry,7 8 = priest,8 9 = fighter,9 10 = wizard,10 11 = cavalry,10 12 = knight,10 [earn] 1=zealot,6 2=cultist,7 3=charm,8 4=orc,9 5=god,10 [up] 1=sun,1 2=bird,1 3=sword,1 4=ram,2 5=skull,2 6=templar,2 7=weep,3 8=plague,3 This isn\'t the only way to create a deck definition, and using an INI file isn\'t the only format, but because it has a nice, simple dependency and the definition is not complex, it works well for this project. Here\'s an example of how it can be used. This sort of code selects a card from the `[card]` deck: > print(deck['card'][tostring(2)]) mystic,1 > print(deck['card'][tostring(12)]) knight,10 The code you use in the actual Battlejack game will require randomness, and must parse the face from the card value (separated by a comma), but those are details for later. This deck provides just 25 cards to generate. That\'s manageable, so now all that\'s left is to make them. And that\'s just what you\'ll do in the next chapter. Homework {#db-work} -------- Installing and learning new libraries is an important part of programming. Nobody codes everything from scratch unless absolutely necessary, because there are so many great libraries out there with much of your work already done for you. Try these hacks: - INI files store key and value pairs; one word correlates to exactly one other word or number. For more complex data structures, there is a format called YAML, which allows you to define multiple levels of information for everything in your data set. Install `lua-yaml` or a similar library for parsing YAML and try to parse some sample data. For an example of a working script, download the code files for this chapter from this book\'s code repository.