{"id":28895737,"url":"https://github.com/jwodder/ratsnake","last_synced_at":"2026-04-25T18:06:48.904Z","repository":{"id":300298047,"uuid":"1005821841","full_name":"jwodder/ratsnake","owner":"jwodder","description":"Snake game in Rust+Ratatui","archived":false,"fork":false,"pushed_at":"2025-09-19T14:04:17.000Z","size":687,"stargazers_count":1,"open_issues_count":17,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-30T11:25:25.954Z","etag":null,"topics":["available-on-crates-io","ratatui","rust","snake-game","terminal","terminal-game","tui"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jwodder.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-20T22:13:38.000Z","updated_at":"2025-09-19T14:04:20.000Z","dependencies_parsed_at":"2025-07-14T12:17:14.816Z","dependency_job_id":"a9a2506f-ca1c-4eb4-9e92-049e3937fde8","html_url":"https://github.com/jwodder/ratsnake","commit_stats":null,"previous_names":["jwodder/ratsnake"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/jwodder/ratsnake","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fratsnake","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fratsnake/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fratsnake/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fratsnake/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jwodder","download_url":"https://codeload.github.com/jwodder/ratsnake/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fratsnake/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279002621,"owners_count":26083425,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["available-on-crates-io","ratatui","rust","snake-game","terminal","terminal-game","tui"],"created_at":"2025-06-21T05:08:27.112Z","updated_at":"2026-04-25T18:06:48.894Z","avatar_url":"https://github.com/jwodder.png","language":"Rust","readme":"[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)\n[![CI Status](https://github.com/jwodder/ratsnake/actions/workflows/test.yml/badge.svg)](https://github.com/jwodder/ratsnake/actions/workflows/test.yml)\n[![codecov.io](https://codecov.io/gh/jwodder/ratsnake/branch/main/graph/badge.svg)](https://codecov.io/gh/jwodder/ratsnake)\n[![Minimum Supported Rust Version](https://img.shields.io/badge/MSRV-1.88-orange)](https://www.rust-lang.org)\n[![MIT License](https://img.shields.io/github/license/jwodder/ratsnake.svg)](https://opensource.org/licenses/MIT)\n[![Built With Ratatui](https://ratatui.rs/built-with-ratatui/badge.svg)](https://ratatui.rs/)\n\n[GitHub](https://github.com/jwodder/ratsnake) | [crates.io](https://crates.io/crates/ratsnake) | [Issues](https://github.com/jwodder/ratsnake/issues) | [Changelog](https://github.com/jwodder/ratsnake/blob/main/CHANGELOG.md)\n\n`ratsnake` is an implementation of the video game [Snake][] in [Rust][] built\nusing the [Ratatui][] library.  Guide the snake around the level to eat fruits,\nmaking it grow longer, but don't run into yourself!\n\n[Snake]: https://en.wikipedia.org/wiki/Snake_(video_game_genre)\n[Rust]: https://www.rust-lang.org\n[Ratatui]: https://ratatui.rs\n\n[![asciicast](https://asciinema.org/a/724406.svg)](https://asciinema.org/a/724406)\n\nInstallation\n============\n\nIn order to install `ratsnake`, you first need to have [Rust and Cargo\ninstalled](https://www.rust-lang.org/tools/install).  You can then build the\nlatest release of `ratsnake` and install it in `~/.cargo/bin` by running:\n\n    cargo install ratsnake\n\nUsage\n=====\n\n    ratsnake [\u003coptions\u003e]\n\nRun `ratsnake` to bring up the program's main menu.\n\n`ratsnake` is optimized for display on 80 column by 24 line terminals.  If your\nterminal is bigger than this, the interface will be centered in the middle.  If\nyour terminal is smaller, you're going to have a bad time.\n\nAll screens in `ratsnake` support directional movement with the arrow keys,\n\u003ckbd\u003eh\u003c/kbd\u003e/\u003ckbd\u003ej\u003c/kbd\u003e/\u003ckbd\u003ek\u003c/kbd\u003e/\u003ckbd\u003el\u003c/kbd\u003e,\n\u003ckbd\u003ew\u003c/kbd\u003e/\u003ckbd\u003ea\u003c/kbd\u003e/\u003ckbd\u003es\u003c/kbd\u003e/\u003ckbd\u003ed\u003c/kbd\u003e, and\n\u003ckbd\u003e2\u003c/kbd\u003e/\u003ckbd\u003e4\u003c/kbd\u003e/\u003ckbd\u003e6\u003c/kbd\u003e/\u003ckbd\u003e8\u003c/kbd\u003e.  In addition, pressing\n\u003ckbd\u003eCtrl\u003c/kbd\u003e+\u003ckbd\u003eC\u003c/kbd\u003e at any point during program execution will\nimmediately end the program.\n\nOptions\n-------\n\n- `-c \u003cfile\u003e`, `--config \u003cfile\u003e` — Read program confguration from `\u003cfile\u003e`.\n  See \"Configuration\" below for more information.\n\n- `-h`, `--help` — Show command-line usage\n\n- `-V`, `--version` — Show current program version\n\nMain Menu\n---------\n\n![Screenshot of the main menu](screenshots/mainmenu.png)\n\nThe main menu allows the user to configure various options for Snake before\nstarting a game.  The options are saved to a file (See \"Configuration\" below)\nthat is loaded on program startup and updated before starting a new game.\n\nThe following options can be set:\n\n- **Wraparound** — If this option is set, the borders of the game level will\n  wrap around so that the snake can pass into one side and come out the\n  opposite.  When this is not set, the snake will die upon coming into contact\n  with a level border.\n\n- **Obstacles** — If this option is set, random obstacles will be placed in the\n  game level; coming into contact with one kills the snake.\n\n- **Fruits** — Set the number of fruits present at all times.  May be any\n  integer from 1 through 10.\n\n- **Level Size** — Set the dimensions of the game level, choosing from small\n  (38×8), medium (53×12), and large (76×19).\n\n### Key Bindings\n\n| Key                                                        | Command                                                |\n| ---------------------------------------------------------- | ------------------------------------------------------ |\n| \u003ckbd\u003ek\u003c/kbd\u003e, \u003ckbd\u003ew\u003c/kbd\u003e, \u003ckbd\u003e8\u003c/kbd\u003e, \u003ckbd\u003eUp\u003c/kbd\u003e    | Move up an item                                        |\n| \u003ckbd\u003ej\u003c/kbd\u003e, \u003ckbd\u003es\u003c/kbd\u003e, \u003ckbd\u003e2\u003c/kbd\u003e, \u003ckbd\u003eDown\u003c/kbd\u003e  | Move down an item                                      |\n| \u003ckbd\u003eh\u003c/kbd\u003e, \u003ckbd\u003ea\u003c/kbd\u003e, \u003ckbd\u003e4\u003c/kbd\u003e, \u003ckbd\u003eLeft\u003c/kbd\u003e  | Decrease or unset the current option                   |\n| \u003ckbd\u003el\u003c/kbd\u003e, \u003ckbd\u003ed\u003c/kbd\u003e, \u003ckbd\u003e6\u003c/kbd\u003e, \u003ckbd\u003eRight\u003c/kbd\u003e | Increase or set the current option                     |\n| \u003ckbd\u003eTab\u003c/kbd\u003e                                             | Move down an item, circling around at the bottom       |\n| \u003ckbd\u003eShift\u003c/kbd\u003e+\u003ckbd\u003eTab\u003c/kbd\u003e                            | Move up an item, circling around at the top            |\n| \u003ckbd\u003eHome\u003c/kbd\u003e                                            | Jump to the first item in the menu                     |\n| \u003ckbd\u003eEnd\u003c/kbd\u003e                                             | Jump to the last item in the menu                      |\n| \u003ckbd\u003eSpace\u003c/kbd\u003e                                           | Toggle the current option                              |\n| \u003ckbd\u003eEnter\u003c/kbd\u003e                                           | Toggle the current option or select the current button |\n| \u003ckbd\u003ep\u003c/kbd\u003e                                               | Play a game of Snake                                   |\n| \u003ckbd\u003e@\u003c/kbd\u003e                                               | Randomize all game options                             |\n| \u003ckbd\u003eH\u003c/kbd\u003e                                               | View high scores                                       |\n| \u003ckbd\u003eq\u003c/kbd\u003e                                               | Quit                                                   |\n\nGame\n----\n\n![Screenshot of a game](screenshots/game.png)\n\nUpon selecting \"Play\" in the main menu, a game of Snake starts immediately with\nthe configured options.  The snake advances one cell at a time at regular\nintervals; the directional keys can be used to change its direction of motion.\nThe goal is to guide the snake to consume fruits (red dots) that randomly\nappear on the level; eating a fruit increases your score by 1 (displayed at the\ntop of the screen) but also makes the snake longer, making it harder to avoid\nself-collisions.\n\nPressing \u003ckbd\u003eEscape\u003c/kbd\u003e or defocusing the terminal during play will pause\nthe game.  While paused, a pop-up menu is displayed, giving you the choice of\nresuming/unpausing, restarting the game using the same options (though\nobstacles will be re-randomized), returning to the main menu, or quitting the\nprogram.\n\nThe game lasts until the snake's head collides with its body, the level border\n(if the wraparound option was not enabled), or an obstacle, all of which kill\nthe snake.  (If you're very skilled, you may also get a game over if you manage\nto fill the level with the snake.)  When the game ends, a message is displayed,\nand you can choose to start a new game with the same options (by pressing\n\u003ckbd\u003er\u003c/kbd\u003e), return to the main menu (by pressing \u003ckbd\u003em\u003c/kbd\u003e), or quit the\nprogram (by pressing \u003ckbd\u003eq\u003c/kbd\u003e).\n\nHigh scores are tracked and saved to a file automatically (See \"Configuration\"\nbelow).  Each combination of game options has its own separate high score.\nNote that quitting a game in the middle of play will not cause a new high score\nto be registered.\n\n\nConfiguration File\n==================\n\n`ratsnake` can be configured via a [TOML](https://toml.io) file whose\ndefault location depends on your OS:\n\n- Linux — `~/.config/ratsnake/config.toml` or `$XDG_CONFIG_HOME/ratsnake/config.toml`\n- macOS — `~/Library/Application Support/ratsnake/config.toml`\n- Windows — `%USERPROFILE%\\AppData\\Local\\ratsnake\\config.toml`\n\nThis file may contain the following tables \u0026 keys, all of which are optional\nunless indicated otherwise:\n\n- `[files]` — Configure data files\n    - `high-scores-dir` (string) — Path to a directory (which `ratsnake` will\n      create if it doesn't already exist) in which high scores will be stored.\n      An initial `~/` will be replaced by the path to the user's home\n      directory.  A relative path will be resolved relative to the directory in\n      which the configuration file is located.  The default path is\n      `$DATA_DIR/highscores/`, where `$DATA_DIR` is defined below.\n    - `ignore-errors` (boolean) — whether to suppress notifications about any\n      errors that occur while reading or writing the options file or high score\n      file\n    - `options-file` (string or boolean) — File path at which `ratsnake` will\n      save \u0026 restore gameplay options.  An initial `~/` will be replaced by the\n      path to the user's home directory.  A relative path will be resolved\n      relative to the directory in which the configuration file is located.\n      Setting this to `false` disables saving \u0026 loading of options.  Setting\n      this to `true` causes the default path to be used, the same as if the\n      option were omitted.  The default path is `$DATA_DIR/options.json`, where\n      `$DATA_DIR` is defined below.\n\n- `[glyphs]` — Set the symbols \u0026 colors used to draw various elements of the\n  game display.  Each of the below keys takes as its value a subtable\n  containing a required `symbol` key (a single-column string) and an optional\n  `style` key (a string as parsed by [`parse-style`][]).  Note that a `symbol`\n  without a `style` will be drawn without any styling.\n    - `collision` — Set the symbol \u0026 style used when the snake collides with\n      itself, an obstacle, or the level border\n    - `fruit` — Set the symbol \u0026 style used for fruit\n    - `obstacle` — Set the symbol \u0026 style used for obstacles\n    - `snake-body` — Set the symbol \u0026 style used for the parts of the snake's\n      body\n    - `snake-head` — Set the symbol \u0026 style used for the snake's head\n        - Unlike the other glyphs, `snake-head.symbol` may alternatively be set\n          to a table with `north`, `south`, `east`, and `west` symbol keys (all\n          required), giving the symbols to use for the snake's head when it's\n          moving in the respective directions\n    - `border` — Set the symbol \u0026 style used for non-wraparound level borders\n        - Unlike most other glyphs, `border.symbol` may alternatively be set to\n          a table with `top`, `bottom`, `left`, `right`, `top-left`,\n          `top-right`, `bottom-left`, and `bottom-right` symbol keys (all\n          required), giving the symbols to use for the respective sides \u0026\n          corners of the border\n    - `wraparound` — Set the symbol \u0026 style used for wraparound level borders.\n      `wraparound.symbol` may alternatively be set to a table the same way as\n      `border.symbol`.\n\n- `[options]` — Set default gameplay options, for use when the options file is\n  absent, disabled, or can't be read\n    - `fruits` (integer from 1 to 10) — how many fruits should be present in a\n      level\n    - `obstacles` (boolean) — whether to generate random obstacles in levels\n    - `size` — set the level size; valid options are `\"small\"`, `\"medium\"`, and\n      `\"large\"` (case sensitive)\n    - `wraparound` (boolean) — whether levels should wrap around at the borders\n\nThe default program configuration is as follows:\n\n```toml\n[files]\nignore-errors = false\n\n# Linux, with XDG_DATA_HOME not set:\nhigh-scores-dir = \"~/.local/share/ratsnake/highscores\"\noptions-file = \"~/.local/share/ratsnake/options.json\"\n\n# macOS:\n#high-scores-dir = \"~/Library/Application Support/ratsnake/highscores\"\n#options-file = \"~/Library/Application Support/ratsnake/options.json\"\n\n# Windows:\n#high-scores-dir = '~\\AppData\\Local\\ratsnake\\highscores'\n#options-file = '~\\AppData\\Local\\ratsnake\\options.json'\n\n[glyphs.snake-head]\nsymbol = { \"north\" = \"v\", south = \"^\", east = \"\u003c\", west = \"\u003e\" }\nstyle = \"bold green\"\n\n[glyphs.snake-body]\nsymbol = \"\\u26AC\"\nstyle = \"bold green\"\n\n[glyphs.fruit]\nsymbol = \"\\u25CF\"\nstyle = \"bright_red\"\n\n[glyphs.obstacle]\nsymbol = \"\\u2588\"\nstyle = \"white\"\n\n[glyphs.collision]\nsymbol = \"\\u00D7\"\nstyle = \"reverse bright_red\"\n\n[glyphs.border]\nstyle = \"none\"\n\n[glyphs.border.symbol]\ntop = \"\\u2500\"\nbottom = \"\\u2500\"\nleft = \"\\u2502\"\nright = \"\\u2502\"\ntop-left = \"\\u250C\"\ntop-right = \"\\u2510\"\nbottom-left = \"\\u2514\"\nbottom-right = \"\\u2518\"\n\n[glyphs.wraparound]\nstyle = \"none\"\n\n[glyphs.wraparound.symbol]\ntop = \"\\u22EF\"\nbottom = \"\\u22EF\"\nleft = \"\\u22EE\"\nright = \"\\u22EE\"\ntop-left = \"\\u00B7\"\ntop-right = \"\\u00B7\"\nbottom-left = \"\\u00B7\"\nbottom-right = \"\\u00B7\"\n\n[options]\nwraparound = false\nobstacles = false\nfruits = 1\nsize = \"large\"\n```\n\n[`parse-style`]: https://github.com/jwodder/parse-style\n\nData Directory\n--------------\n\nBy default, options and high scores are saved in a data directory in your home\nfolder, referred to above as `$DATA_DIR`.  The location of this directory\ndepends on your OS:\n\n- Linux — `~/.local/share/ratsnake/` or `$XDG_DATA_HOME/ratsnake/`\n- macOS — `~/Library/Application Support/ratsnake/`\n- Windows — `%USERPROFILE%\\AppData\\Local\\ratsnake\\`\n\nAcknowledgements\n================\n\nMuch of `ratsnake`'s functionality was inspired by\n[`nsnake`](https://github.com/alexdantas/nSnake) by Alexandre Dantas (no longer\nmaintained).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwodder%2Fratsnake","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjwodder%2Fratsnake","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwodder%2Fratsnake/lists"}