Welcome to Csnake's Development Documentation!
In this document, you will find:
- License
- Code Structure
- Defines
- #define name
- Description
- Default Value
- Custom Types
- Type Name
- Corresponds To
- Custom Objects
- Object Name
- Object Description
- Items contained in Object
- Functions
- Function Type
- Function Name
- Function Description
- Arguments
- Global Variables
- Type
- Variable Name
- Description
- Default Value
This project is licensed under the GNU General Public License version 3, abbreviated GNU GPLv3.
Project originally made by Matteo Salonia <saloniamatteo@pm.me>
csnake.c is structured in the following way:
- Comment describing what the project is, who made it, etc.
- "#include"s
- "#define"s
- Custom types
- typedefs
- enums
- structs
- Global Variables
- Function Prototypes
- Function Declarations
- Main Function (See below)
Overrall, the code is around 400 Single Lines Of Code (SLOC).
The following are "#define"d in Csnake:
| #define Name | Description | Default Value |
|---|---|---|
| _FORTIFY_SOURCE | Fortify source | 2 |
| _POSIX_C_SOURCE | Which POSIX C standard to follow | 200809L |
| __CSNAKE_MAJ_VER | Csnake Major Version (Str) | "1" |
| __CSNAKE_MAJ_NVER | Csnake Major Version (Num) | 1 |
| __CSNAKE_MIN_VER | Csnake Minor Version (Str) | "3" |
| __CSNAKE_MIN_NVER | Csnake Minor Version (Num) | 3 |
| __CSNAKE_VERSION | Csnake Version (MAJ + MIN) | "1.2" (MAJ "." MIN) |
| SNAKESIZE | Maximum Snake size | 100 |
| TAIL_SIZE | Default Tail Length | 3 |
| FOOD_CHAR | Which Character to use to display Food | "@" |
| SNAKECHAR | Which Character to use to display Snake | ACS_CKBOARD |
| DIFF_EASY | Window Timeout in ms for Easy Difficulty | 90 |
| DIFF_MEDI | Window Timeout in ms for Medium Difficulty | 65 |
| DIFF_HARD | Window Timeout in ms for Hard Difficulty | 50 |
| DIFF_XTRM | Window Timeout in ms for Extreme Difficulty | 35 |
| RAND(min, max) | Macro to generate random number between min and max | ((rand() % (max - min + 1)) + min) |
Csnake has the following local custom types: (denoted with the "_ct" suffix)
| Type Name | Corresponds to |
|---|---|
| uint32_ct | unsigned int |
| uint8_ct | short unsigned int |
Csnake has the following local custom objects:
| Object Name | Object Description | Items contained in Object |
|---|---|---|
| COORD | Coordinate object | int x, int y |
| FOOD | Food object | int x, int y, int count |
Csnake has the following functions:
| Function Type | Function Name | Function Description | Arguments |
|---|---|---|---|
| WINDOW * | newsubwin | Create a new sub-window with default borders, and return it. | int height, int width, int startx, int starty, char *title |
| void | diffToWinTimeout | Convert difficulty to ncurses window timeout. | uint8_ct diff |
| char * | diffStr | Convert diffuculty to human-readable string, and return it. | void |
| int | setDiff | Set difficulty from string, and return the corresponding integer. | char *arg |
| void | printHelp | Print help and usage. | char *progname |
| void | newFood | Generate new food coordinates. | void |
| int | checkFile | Check if we can write to file, and return -1 if we are trying to write to ourselves, 0 if the file cannot be opened, 1 if it can be opened. | char *file, char *name |
| void | saveScore | Save scores to file, according
to savefile variable. |
void |
| void | endSnk | Exit Csnake cleanly, showing total score, total apples eaten, and showing difficulty. | WINDOW *win |
| uint32_ct | randScore | Generate a new random integer between 1 and 10, and return the value. (Used for random score generation) | void |
| void | pauseMenu | Create a new pause menu window, to pause the game. | void |
| void | exitConfirm | Check if user really wants to exit game. | WINDOW *win |
| void | scrUpd | Update the screen, drawing the food, and the snake, on the screen. | WINDOW *win |
Csnake has the following global variables:
| Type | Variable Name | Description | Default Value |
|---|---|---|---|
| uint32_ct | x | Screen width | 0 |
| uint32_ct | y | Screen height | 0 |
| uint32_ct | max_x | Max Screen width | 0 |
| uint32_ct | max_y | Max Screen height | 0 |
| uint32_ct | nx | Next x coordinate | 0 |
| uint32_ct | ny | Next y coordinate | 0 |
| uint32_ct | tail_len | Tail Length | TAIL_SIZE |
| DIRECTION | direction | Current snake direction | RIGHT |
| COORD | snake[SNAKESIZE] | Snake Object | {0} |
| FOOD | food | Food Object | {0} |
| uint32_ct | score | Player Score | 0 |
| uint8_ct | diff | Difficulty | 1 |
| uint8_ct | win_timeout | Window Timeout | 65 |
| uint32_ct | usr_x | User-defined x | 0 |
| uint32_ct | usr_y | User-defined y | 0 |
| bool | borders | Are borders enabled? | false |
| char | filename[100] | Default file used to save scores | {0} |
| bool | savescore | Save scores? | false |
The actual core of the program is located in the main() function.
The main() function is structured like this:
- Locale Initialisation (C locale)
- Command-line argument handling
- Loop to parse each argument
- Ncurses Initialisation
- Window Initialisation
- Screen coordinate saving
- Coordinate Adjusting
- Various option finalisations
- Show program info
- Game Section
- Snake initialisation
- Food creation
- (Optional) Show Borders
- Direction Key handling (hjkl or arrow keys)
- Food handling
- Snake movement handling
Firstly, the locale is initialised with the setlocale() function,
located in the locale.h header.
Then, we have to parse command-line options/arguments, using getopt_long,
which lets us parse both short and long options.
Following that, we initialise the ncurses window, and we check if the user
coordinates have been passed: if they aren't 0, that means the user has
provided custom coordinates, so we set max_x and/or max_y to the custom
coordinates, which correspond to the width (x) and height (y) of the screen.
We then finalise various Ncurses options, such as:
- Do not echo keypresses (
noecho()) - Disable line buffering (
cbreak()) - Don't display cursor (
curs_set(0)) - Enable keypad, allowing us to use cursor keys (
keypad(win, 1)) - Set window timeout, according to difficulty chosen by user (
wtimeout(win, win_timeout))
Next, we briefly show cnake's info, showing the current version,
and who made the program (Matteo Salonia).
Finally, we enter the game section, where we have to actually compute the game logic:
- Initialise snake position, setting the default position
- Set new food coordinates (default coordinates are screen center)
- Endless loop
- Always draw score & difficulty on top left corner
- Get key press from user
- Handle key press
- Checking if a direction key (hjkl or arrow keys) was pressed
- Handle the snake movement
- Check if ESC (written as
^[) was pressed - Pause the game
- Check if ESC (written as
- Check if q was pressed
- Check if the user actually wants to exit or not.
Obviously, the user is not forced to press "q" to quit, in fact they can just
press
CTRL+Cto exit, but their final scores won't be shown. (Note: this might change in a future version, where an option may be passed to save scores to a file)
- Check if the user actually wants to exit or not.
Obviously, the user is not forced to press "q" to quit, in fact they can just
press
- Set the snake's next coordinates, which always correspond to snake's head
- Handle direction, changing the next coordinates
- Check if snake has eaten food
- Update food count
- Set new tail position, increasing it by 1
- Add a random value between 1 and 10 to user score
- If the snake has not eaten food, redraw the snake
- Check if the snake has collided into itself
- Check if the snake has hit screen edges
- Redraw Screen
- If the endless loop somehow fails, end game cleanly