{"id":20339874,"url":"https://github.com/uditkarode/unocab","last_synced_at":"2025-03-04T14:43:57.266Z","repository":{"id":176720846,"uuid":"659322100","full_name":"uditkarode/unocab","owner":"uditkarode","description":"🎨 An Uno game engine.","archived":false,"fork":false,"pushed_at":"2023-06-27T16:33:59.000Z","size":38,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-14T18:08:38.155Z","etag":null,"topics":["uno"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/uditkarode.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2023-06-27T15:24:29.000Z","updated_at":"2024-10-30T19:38:58.000Z","dependencies_parsed_at":"2023-10-21T16:15:07.432Z","dependency_job_id":null,"html_url":"https://github.com/uditkarode/unocab","commit_stats":null,"previous_names":["uditkarode/unocab"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uditkarode%2Funocab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uditkarode%2Funocab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uditkarode%2Funocab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uditkarode%2Funocab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uditkarode","download_url":"https://codeload.github.com/uditkarode/unocab/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241867649,"owners_count":20033815,"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","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":["uno"],"created_at":"2024-11-14T21:18:50.468Z","updated_at":"2025-03-04T14:43:57.261Z","avatar_url":"https://github.com/uditkarode.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Unocab\n\nUnocab is an UNO game engine.\n\n# Installation\n\n### Deno\n```typescript\nimport { Game } from \"https://deno.land/x/unocab@v0.8.0/mod.ts\";\n```\n\n### Node\n`npm install unocab`\n\n# Usage\n\n```typescript\n// On creation of a Game, an UNO deck of 108 cards is\n// shuffled and assigned to `game.state.cache.deck`.\nconst game = new Game({\n  // Whether to stack +2s. If this is enabled, and\n  // say three +2s are played one after the other,\n  // the person to draw next will pick up 6 cards.\n  // This option is enabled by default.\n  stackPlusTwos: true,\n\n  // The initial seed determines all the random events\n  // of the game. Hence if you create two games with\n  // the same initial seed and the same number of players\n  // join the game at the same time, the shuffled deck and\n  // the hands of the players will be the same.\n  initialSeed: \"unocab rocks!\",\n\n  // Explained in the next README section.\n  shorthandMode: false,\n});\n\n// At the start of the game, the engine also plays the\n// first card of the deck which is not a +4 or color\n// switcher. After this point, players continue the\n// game based on the type and color of this card.\n\n// Whenever new players join, a hand of 7 cards is\n// assigned to each of them. A hand is formed by\n// drawing the top card of the deck 7 times. This\n// is random, since the deck has been shuffled.\nconst [p1, p2] = [\"player1\", \"player2\"];\ngame.join(p1, p2);\n\n// let's assume the first card was a Red 4, and p1 has\n// a Red 6 and a +4.\ngame.play(p1, { type: \"six\", color: \"red\" });\n\ngame.draw(p2);\ngame.pass(p2);\n\ngame.play(p1, { type: \"plus-four\" });\ngame.switchColor(p1, \"blue\");\n\ngame.callBluff(p2);\n\n// ... more moves\n\nconst end = game.hasEnded();\nif (end) console.log(end.loser + \" lost the game!\");\n```\n\n# Full vs Shorthand mode\n\nDuring creation of a `Game`, you can optionally pass in `shorthandMode: true`. In shorthand\nmode, the engine only keeps as much information about the game as is needed for it to\nfunction. Otherwise, **and by default**, **all** information about the game is kept in the events\narray (`game.state.events`). This allows you to have a history of all the happenings in that\nparticular game, and also allows you to jump to an arbitrary point in the game. For example,\nto undo a move, you could use `game.jumpToEventIndex(-2)`. This\nfunction is not usable in shorthand mode, and the events array will only keep 5 events at most.\n\n**TLDR**: Use shorthand mode if you don't want to use `jumpToEventIndex` or keep the entire game history.\n\n# Serialising and Deserialising\n\nA game can be serialised into JSON using `game.serialise()`, and cloned using `game.clone()`.\nA game can be deserialised using `new Game({ serialisedState: gameJson })`.\n\nHowever, when deserialising a game, arguments like `shorthandMode` or `stackPlusTwos` are not\nallowed, since they were already set when the game was being initiated.\n\n# Error Reporting\n\nIf a player tries to perform an invalid move, such as drawing twice in a row or playing a card\nthat is not allowed, an `UnocabError` will be thrown. The message provides an adequate description\nof what the problem was, but you can also access information pertaining to the error using the `code` and `data` fields in an `UnocabError`. Please have a look at `errors.ts` for the variations of error codes and the data they provide.\n\n# Types\n\nUnocab provides Zod types for most of the objects it uses in case you're building something like a REST API and want to verify the structure. Please glance over the `types.ts` file to figure out what Zod types are provided.\n\n# GameEvent\n\nA game event is an object with a `type` that denotes what kind of event it is (e.g. `draw` or `card_played`), and additional info about that particular event, such as the `card` property in a `card_played` event.\n\nIt looks like `{ type: \"card_played\", by: \"player-one\", card: { type: \"six\", color: \"red\" } }`.\n\n\u003e NOTE: In full mode (aka not shorthand mode), the events array will also contain events with type `game_info`. These events are not a result of player's actions, but are added by the engine to denote certain happenings. For example, when a player calls bluff, a `game_info` event will be added afterwards to signify whether the bluff call succeeded or failed. This can be helpful for something like implementation of animations when re-playing the game.\n\nFor more information about what events exist, please glance over the `types.ts` file.\n\n# Fetching valid events\n\nTo obtain a list of \"options\" for the active player in a game, use `game.validEvents(playerId)`.\nThis will return an array of `GameEvent`s which the player is allowed to act on. These events can\ndirectly be used like `game.processNewEvent(event)`, which acts as an alternative to functions like\n`game.draw` or `game.pass`, which internally use `processNewEvent` as well.\n\n# Demo implementations\n\nPlease refer to `impls/cli-uno.ts` for a cli-based game with an AI.\nThere's also `impls/autoplay.ts`, which is an AI vs AI game.\n\n(AI here naturally means if conditions, ofcourse!)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuditkarode%2Funocab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuditkarode%2Funocab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuditkarode%2Funocab/lists"}