{ "info": { "author": "Thomas Grainger", "author_email": "board@graingert.co.uk", "bugtrack_url": null, "classifiers": [ "Environment :: Console", "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3" ], "description": "Board Game for Python Dojos\n===========================\n\nIntroduction\n------------\n\nOften, when running a Python Dojo, we've ended up with a challenge\nbased around some kind of board or tile-based landscape. In these\nsituations it's not uncommon to spend a lot of the time building up\nyour basic board functionality in order to support the more interesting\ngameplay algorithm.\n\nThis module implements a general-purpose board structure which\nhas the functionality needed for a range of purposes, and lends itself\nto being subclassed for those particular needs.\n\nDependencies\n------------\n\nNone - stdlib only\n\nTests\n-----\n\nFairly decent coverage (not actually checked with coverage.py): test.py\n\nGetting Started\n---------------\n\nInstall with pip::\n\n pip install board\n\nAbsolutely basic usage::\n\n import board\n #\n # Produce a 3x3 board\n #\n b = board.Board((3, 3))\n\n b[0, 0] = \"X\"\n b[1, 0] = \"O\"\n\nUsage\n-----\n\nBoard is an n-dimensional board, any of which dimensions can be of\ninfinite size. (So if you have, say, 3 infinite dimensions, you have\nthe basis for a Minecraft layout). Dimensions are zero-based.\n\nCells on the board are accessed by item access, eg board[1, 2] or\nlandscape[1, 1, 10].\n\nA board can be copied, optionally along with its data by means of the\n.copy method. Or a section of a board can be linked to the original\nboard by slicing the original board::\n\n b1 = board.Board((9, 9))\n b1[1, 1] = 1\n b2 = b1.copy()\n b3 = b1[:3, :3]\n\nNote that the slice must include all the dimensions of the original\nboard, but any of those subdimensions can be of length 1::\n\n b1 = board.Board((9, 9, 9))\n b2 = b1[:3, :3, :1]\n\nA sentinel value of Empty indicates a position which is not populated\nbecause it has never had a value, or because its value has been deleted::\n\n b1 = board.Board((3, 3))\n assert b1[1, 1] is board.Empty\n b1.populate(\"abcdefghi\")\n assert b1[1, 1] == \"e\"\n del b1[1, 1]\n assert b1[1, 1] is board.Empty\n\nIterating over the board yields its coordinates::\n\n b1 = board.Board((2, 2))\n for coord in b1:\n print(coord)\n #\n # => (0, 0), (0, 1) etc.\n #\n\nIteration over a board with one or more infinite dimensions will work\nby iterating in chunks::\n\n b1 = board.Board((3, 3, board.Infinity))\n for coord in b1:\n print(b1)\n\nTo see coordinates with their data items, use iterdata::\n\n b1 = board.Board((2, 2))\n b1.populate(\"abcd\")\n for coord, data in b1.iterdata():\n print(coord, \"=>\", data)\n\n\nTo read, write and empty the data at a board position, use indexing::\n\n b1 = board.Board((3, 3))\n b1.populate(\"abcdef\")\n print(b1[0, 0]) # \"a\"\n\n b1[0, 0] = \"*\"\n print(b1[0, 0]) # \"*\"\n\n del b1[0, 0]\n print(b1[0, 0]) # \n\nTo test whether a coordinate is contained with the local coordinate space, use in::\n\n b1 = board.Board((3, 3))\n (1, 1) in b1 # True\n (4, 4) in b1 # False\n (1, 1, 1) in b1 # InvalidDimensionsError\n\nOne board is equal to another if it has the same dimensionality and\neach data item is equal::\n\n b1 = board.Board((3, 3))\n b1.populate(\"abcdef\")\n b2 = b1.copy()\n b1 == b2 # True\n b2[0, 0] = \"*\"\n b1 == b2 # False\n\n b2 = board.Board((2, 2))\n b2.populate(\"abcdef\")\n b1 == b2 # False\n\nTo get a crude view of the contents of the board, use .dump::\n\n b1 = board.Board((3, 3))\n b1.populate(\"abcdef\")\n b1.dump()\n\nTo get a grid view of a 2-dimensional board, use .draw::\n\n b1 = board.Board((3, 3))\n b1.populate(\"OX XXOO \")\n b1.draw()\n\n\nTo populate the board from an arbitrary iterator, use .populate::\n\n def random_letters():\n import random, string\n while True:\n yield random.choice(string.ascii_uppercase)\n\n b1 = board.Board((4, 4))\n b1.populate(random_letters())\n\nTo clear the board, use .clear::\n\n b1 = board.Board((3, 3))\n b1.populate(range(10))\n b1.clear()\n list(b1.iterdata()) # []\n\nA board is True if it has any data, False if it has none::\n\n b1 = board.Board((2, 2))\n b1.populate(\"abcd\")\n bool(b1) # True\n b1.clear()\n bool(b1) # False\n\nThe length of the board is the product of its dimension lengths. If any\ndimension is infinite, the board length is infinte. NB to find the\namount of data on the board, use lendata::\n\n b1 = board.Board((4, 4))\n len(b1) # 16\n b1.populate(\"abcd\")\n len(b1) # 16\n b1.lendata() # 4\n b2 = board.Board((2, board.Infinity))\n len(b2) # Infinity\n\nTo determine the bounding box of the board which contains data, use .occupied::\n\n b1 = board.Board((3, 3))\n b1.populate(\"abcd\")\n list(c for (c, d) in b1.iterdata()) # [(0, 0), (0, 1), (0, 2), (1, 0)]\n b1.occupied() # ((0, 0), (1, 2))\n\nTo test whether a position is on any edge of the board, use .is_edge::\n\n b1 = board.Board((3, 3))\n b1.is_edge((0, 0)) # True\n b1.is_edge((1, 1)) # False\n b1.is_edge((2, 0)) # True\n\nTo find the immediate on-board neighbours to a position along all dimensions::\n\n b1 = board.Board((3, 3, 3))\n list(b1.neighbours((0, 0, 0)))\n # [(0, 1, 1), (1, 1, 0), ..., (1, 0, 1), (0, 1, 0)]\n\nEXPERIMENTAL: To iterate over all the coords in the rectangular space between\ntwo corners, use .itercoords::\n\n b1 = board.Board((3, 3))\n list(b1.itercoords((0, 0), (1, 1))) # [(0, 0), (0, 1), (1, 0), (1, 1)]\n\nEXPERIMENTAL: To iterate over all the on-board positions from one point in a\nparticular direction, use .iterline::\n\n b1 = board.Board((4, 4))\n start_from = 1, 1\n direction = 1, 1\n list(b1.iterline(start_from, direction)) # [(1, 1), (2, 2), (3, 3)]\n direction = 0, 2\n list(b1.iterline(start_from, direction)) # [(1, 1), (1, 3)]\n\nProperties\n----------\n\nTo determine whether a board is offset from another (ie the result of a slice)::\n\n b1 = board.Board((3, 3))\n b1.is_offset # False\n b2 = b1[:1, :1]\n b2.is_offset # True\n\nTo determine whether a board has any infinite or finite dimensions::\n\n b1 = board.Board((3, board.Infinity))\n b1.has_finite_dimensions # True\n b1.has_infinite_dimensions # True\n b2 = board.Board((3, 3))\n b1.has_infinite_dimensions # False\n b3 = board.Board((board.Infinity, board.Infinity))\n b3.has_finite_dimensions # False\n\nLocal and Global coordinates\n----------------------------\n\nSince one board can represent a slice of another, there are two levels\nof coordinates: local and global. Coordinates passed to or returned from\nany of the public API methods are always local for that board. They\nrepresent the natural coordinate space for the board. Internally, the\nmodule will use global coordinates, translating as necessary.\n\nSay you're managing a viewport of a tile-based dungeon game where the\nmaster dungeon board is 100 x 100 but the visible board is 10 x 10.\nYour viewport board is currently representing the slice of the master\nboard from (5, 5) to (14, 14). Changing the item at position (2, 2) on\nthe viewport board will change the item at position (7, 7) on the master\nboard (and vice versa).\n\nAs a user of the API you don't need to know this, except to understand\nthat a board slice is essentially a view on its parent. If you wish\nto subclass or otherwise extend the board, you'll need to note where\ncoordinate translations are necessary.\n\n\n\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/graingert/dojo-board", "keywords": "", "license": "unlicensed", "maintainer": "", "maintainer_email": "", "name": "board", "package_url": "https://pypi.org/project/board/", "platform": "", "project_url": "https://pypi.org/project/board/", "project_urls": { "Homepage": "https://github.com/graingert/dojo-board" }, "release_url": "https://pypi.org/project/board/0.0.0.post0/", "requires_dist": null, "requires_python": "", "summary": "Standard Board mechanism for Dojo tasks", "version": "0.0.0.post0" }, "last_serial": 3542830, "releases": { "0.0.0": [ { "comment_text": "", "digests": { "md5": "b6082a424a8ebb59679d14b768bd8a88", "sha256": "592416972460ca424bb2a98ab85f1d2748b49cfb9d1d0336f93f5344dcb0a863" }, "downloads": -1, "filename": "board-0.0.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b6082a424a8ebb59679d14b768bd8a88", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 7100, "upload_time": "2018-02-01T19:56:49", "url": "https://files.pythonhosted.org/packages/e2/e2/bbb57c79d75088c0448709b89e7097fb3265a0e1652ec240314294506633/board-0.0.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "488269a8ebfebb2442d2ebf145bd645c", "sha256": "08148e7ad2cfc90ce84e3e45db51032a1ae38802e698319ca82291e896037eb2" }, "downloads": -1, "filename": "board-0.0.0.tar.gz", "has_sig": false, "md5_digest": "488269a8ebfebb2442d2ebf145bd645c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4599, "upload_time": "2018-02-01T19:56:48", "url": "https://files.pythonhosted.org/packages/71/19/78cdca3441e09d382ff3d8db0ba1211d714b7ab3261a11dcf12b142da6e2/board-0.0.0.tar.gz" } ], "0.0.0.post0": [ { "comment_text": "", "digests": { "md5": "cd37903ddef850cf69e5850ae5533e4c", "sha256": "831de92f159ae43d4b4458155a7156947fd48da7886d65598f0882453abe5b6d" }, "downloads": -1, "filename": "board-0.0.0.post0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "cd37903ddef850cf69e5850ae5533e4c", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 12477, "upload_time": "2018-02-01T20:29:06", "url": "https://files.pythonhosted.org/packages/a9/84/5a574f9f1af2ec3fa47856c9cc76cc5d7607d6fe26d8d032722b14734816/board-0.0.0.post0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "251b4a129d016913d1c949e3c90e5180", "sha256": "149e5dd87be1835ecfea76fc25bba29dc5ee9ed5088338e61557124601b9eaf4" }, "downloads": -1, "filename": "board-0.0.0.post0.tar.gz", "has_sig": false, "md5_digest": "251b4a129d016913d1c949e3c90e5180", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9485, "upload_time": "2018-02-01T20:29:05", "url": "https://files.pythonhosted.org/packages/44/aa/de9c002e7726425ea628f8b576a33d172ba792f7e2dd07e1130ad651974f/board-0.0.0.post0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "cd37903ddef850cf69e5850ae5533e4c", "sha256": "831de92f159ae43d4b4458155a7156947fd48da7886d65598f0882453abe5b6d" }, "downloads": -1, "filename": "board-0.0.0.post0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "cd37903ddef850cf69e5850ae5533e4c", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 12477, "upload_time": "2018-02-01T20:29:06", "url": "https://files.pythonhosted.org/packages/a9/84/5a574f9f1af2ec3fa47856c9cc76cc5d7607d6fe26d8d032722b14734816/board-0.0.0.post0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "251b4a129d016913d1c949e3c90e5180", "sha256": "149e5dd87be1835ecfea76fc25bba29dc5ee9ed5088338e61557124601b9eaf4" }, "downloads": -1, "filename": "board-0.0.0.post0.tar.gz", "has_sig": false, "md5_digest": "251b4a129d016913d1c949e3c90e5180", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9485, "upload_time": "2018-02-01T20:29:05", "url": "https://files.pythonhosted.org/packages/44/aa/de9c002e7726425ea628f8b576a33d172ba792f7e2dd07e1130ad651974f/board-0.0.0.post0.tar.gz" } ] }