{"id":21877567,"url":"https://github.com/marvk/sigmarsgarden","last_synced_at":"2026-02-10T18:32:01.731Z","repository":{"id":82026116,"uuid":"382641082","full_name":"marvk/sigmarsgarden","owner":"marvk","description":"Opus Magnum's Sigmar's Garden Autosolver, using OpenCV Template Matching","archived":false,"fork":false,"pushed_at":"2022-09-29T09:21:37.000Z","size":221,"stargazers_count":4,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-02T10:22:59.293Z","etag":null,"topics":["backtracking","classification","computer-vision","constraint-satisfaction-problem","cv","image-classification","image-classifier","opencv","opus-magnum","sigmars-garden","template-matching","zachtronics"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marvk.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":"2021-07-03T14:54:49.000Z","updated_at":"2024-08-09T19:17:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"fe070240-754d-4ba2-a4bc-c123a52af28a","html_url":"https://github.com/marvk/sigmarsgarden","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/marvk/sigmarsgarden","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marvk%2Fsigmarsgarden","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marvk%2Fsigmarsgarden/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marvk%2Fsigmarsgarden/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marvk%2Fsigmarsgarden/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marvk","download_url":"https://codeload.github.com/marvk/sigmarsgarden/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marvk%2Fsigmarsgarden/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29311116,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-10T17:48:59.043Z","status":"ssl_error","status_checked_at":"2026-02-10T17:45:37.240Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["backtracking","classification","computer-vision","constraint-satisfaction-problem","cv","image-classification","image-classifier","opencv","opus-magnum","sigmars-garden","template-matching","zachtronics"],"created_at":"2024-11-28T08:09:36.835Z","updated_at":"2026-02-10T18:32:01.726Z","avatar_url":"https://github.com/marvk.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sigmar's Garden Autosolver \n\n### Demo\n\nhttps://user-images.githubusercontent.com/6569856/124358296-f5bf8b80-dc1f-11eb-9907-ba2046189858.mp4\n\n## Implementation Details\n\n### Image processing ([BoardVision.java](src/main/java/net/marvk/sigmarsgarden/BoardVision.java))\n\nI'm using OpenCV's [Template Matching](https://docs.opencv.org/3.4/de/da9/tutorial_template_matching.html) functionality to compare captured tiles to previously classified examples. \n\nI initially thought about using a structual metric, for example SSIM, but it turned out that perfect classification could be achieved with a template matching approach and some preprocessing, despite the reflections on the tiles.\n\nI'm using several preprocessing steps, namely: \n\n* Tiling the board\n* Cropping tiles to exclude irrelevant details that might make it harder for the classifier to recognise the relevant parts of the image\n* Convert to monochrome, as it turned out, value was the only channel needed to achieve perfect matching\n* Equalize histogram to take advantage of the full range of available values\n* Several contrast increasing steps to separate the relevant parts of the tiles\n\nAn example process can be found here:\n\nhttps://user-images.githubusercontent.com/6569856/124358326-11c32d00-dc20-11eb-9bfa-9909b94c2a2c.mp4\n\n### Move Generation ([Board.java](src/main/java/net/marvk/sigmarsgarden/Board.java))\n\nOnce the board is obtailed, generating valid moves is easy enough. First, find tiles that are playable, aka that have three successive free spaces.\n\nThen generate all combinations of one, two and five tiles. \n\nThen reject \n\n* all one-moves that \n  * aren't gold\n* all two-moves that \n  * don't have two Elements\n  * don't have two Salt\n  * don't have one Salt and one Element\n  * don't have Mors and Vitae\n  * don't have Quicksilver and any Metal\n* all five-moves that\n  * don't have every Element and the Universal tile\n\nAdditionally, reject all metal moves that are blocked by a previous metal.\n\n### Solving ([BoardSolver.java](src/main/java/net/marvk/sigmarsgarden/BoardSolver.java))\n\nSolving the game is probably the easiest part of the project. I'm using a simple [Backtracking](https://en.wikipedia.org/wiki/Backtracking) algorithm, enhanced by a [Transposition Table](https://en.wikipedia.org/wiki/Transposition_table), with hashes generated from two `long`s, in which each bit represents a board hex and is set if the corresponding hex is empty.\n\n### Playing the game ([BoardRobot.java](src/main/java/net/marvk/sigmarsgarden/BoardVision.java))\n\nThe game is played by a [java.awt.Robot](https://docs.oracle.com/en/java/javase/16/docs/api/java.desktop/java/awt/Robot.html) that is able to start a new game, captures board and click tiles to play moves.\n\n## Running the project\n\n### Prerequisites: \n\n* JDK 15 or newer\n* Maven\n\n### Instructions\n\n* Clone this project and navigate into it's root directory\n* Run `mvn clean compile` to compile the project\n* Run `mvn exec:java` to run the project. It will start solving automatically. Please note the limitations in the Acknowledgements \u0026 Limitations section of this readme.\n\n## Acknowledgements \u0026 Limitations\n\nIf you want to run this yourself, be warned that the code as it stands now is optimized for 1080p resolution and 100% scaling and will probably break on anything but 1080p 100%.\n\nThis project uses OpenCV.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarvk%2Fsigmarsgarden","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarvk%2Fsigmarsgarden","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarvk%2Fsigmarsgarden/lists"}