{"id":5603,"date":"2018-12-23T14:00:56","date_gmt":"2018-12-23T14:00:56","guid":{"rendered":"http:\/\/writeasync.net\/?p=5603"},"modified":"2018-12-22T23:20:04","modified_gmt":"2018-12-22T23:20:04","slug":"building-an-adventure-game-part-3","status":"publish","type":"post","link":"http:\/\/writeasync.net\/?p=5603","title":{"rendered":"Building an adventure game: part 3"},"content":{"rendered":"<p>I last left off on <a href=\"http:\/\/writeasync.net\/?p=5599\">Day 8 of my adventure game project<\/a>. We continue from Day 9 today.<\/p>\n<h2>Day 9<\/h2>\n<p>After warming up with <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/7ba461e05343e511cb87d9395209e58923c7b32b\">a simple rename<\/a>, I decide I don&#8217;t like how <code>TextConsole<\/code> and <code>InputLoop<\/code> interact. If I want to go all-in with my message passing design, I should have these classes interact via a message protocol instead. To prepare for this, I <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/652c1746d8ed79f610b4bf0151fe89c04b12854e\">rename the existing <code>InputLoop<\/code> to <code>OldInputLoop<\/code><\/a> to avoid breaking everything while I experiment with a new class. I set up the <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/f9818bf0bcb18bec523d6ec5048a0fa6ec0344ee\">skeletal new version of <code>InputLoop<\/code><\/a> which will eventually use two messages for handling input requests and detecting the end of input. After filling out the behavior driven by a few tests, I <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/e3ae179f210e8cdc601aaf8204f5fa0e16f522aa\">end the day with a Dispose scenario<\/a>. So far, only these tests are using this new code; I&#8217;ll have to wait till the next day to continue.<\/p>\n<h2>Day 10<\/h2>\n<p>Following the pattern of the previous day, I get to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/03b73bf0a550ec7bbfc3d9b1ae281f6ca1d0203d\">work on <code>TextConsole<\/code> by first renaming it to <code>OldTextConsole<\/code><\/a>. I have to admit I don&#8217;t normally follow this workflow of renaming X to OldX, but I rather like it. Again, I sprout the <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/602925c307ff86cdc1a900940b12e775a26cf88b\">new <code>TextConsole<\/code> into existence with a simple initial test<\/a>. <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/cfd065dff88b8ebc8df7712a44110bb76c6d3541\">A few tests later<\/a>, I have a complete enough implementation to move forward. This revamped <code>TextConsole<\/code> accepts the <code>InputRequestedMessage<\/code> from yesterday to handle reads and the <code>OutputMessage<\/code> to handle writes. It also emits <code>InputReceivedMessage<\/code> (when a line is read) and <code>InputEndedMessage<\/code> (when the stream has ended). I&#8217;m now ready to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/1a2661d1c45e495f5b82a5bcc301af32e6cf0d88\">delete the <code>OldX<\/code> classes and use the new ones<\/a>.<\/p>\n<p>The next order of business is to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/c8dcc74085fbe8bd690a7833e5dbad8c0d4eeaf6\">add a description to the room<\/a>. After all, a text adventure game needs descriptive language to help immerse the user into its fantasy world.<\/p>\n<p>Finally, I want to handle some of the input scenarios a little better. I would rather not respond at all to completely empty input, so I work on <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/027ffa4b0d87e75b58434746c24db0cb039ee036\">the receive side<\/a> and <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/5e77c8638955e4494b4b991b0486fafd02722a4c\">the send side<\/a> a bit. Also, the input is lacking a prompt, so I <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/8ce9ca1e5a1ed5e7b80f04a12e338706ca3bde30\">add that functionality<\/a>. In the final two commits of this day, I go old school and <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/917553a57309ed163394b31ff9272bec131f6e7e\">add a &#8216;&gt;&#8217; prompt<\/a> to the sample game and <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/63850b5da1e77ea1a5347f854cb3083dc8b45652\">validate the empty input scenario<\/a>.<\/p>\n<h2>Day 11<\/h2>\n<p>This day is relatively short in commits but long on potential. I decide to work on the &#8216;look&#8217; verb, a mainstay of the genre. I start by <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/8ab14b5794032a7f4acdb06af8680781286c20af\">adding a look handler to the sample game<\/a>. Then I <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/3505123c213761c7e98a386ebc483cf78078297b\">incorporate similar code into the core Room<\/a> using a <code>Look<\/code> method. As a result, I <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/15d7c1b004741007fbe582a73caa90977c1dcd57\">remove the custom game code and use the new Look method directly<\/a>.<\/p>\n<p>So far, we can look at the room as a whole, but how about looking at an object in the room? I will need to handle a noun for this verb. I start with <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/3c146f0c110251445e555289575359feebe6f0d6\">the unknown case<\/a> first and then move on to a <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/9596ec4d3d3e0ce16502abb98a258221ebe8b687\">custom noun case<\/a> (<code>LookAt<\/code>). This functionality suffices to now allow me to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/4b24e9d7f1ccd3cd7cdf668a3450ab628da9dc4d\">add a &#8220;table&#8221; to the MainRoom in the sample game<\/a>.<\/p>\n<h2>Day 12<\/h2>\n<p>Today I decide to work on one of the core features for any adventure game &#8212; the room map. The map determines how rooms are connected and allows travel between them. The first step is <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/b0b4f72f77d9dea8f0d29e4e5cab90bd04fa722b\">writing a test to exercise adding two &#8220;points&#8221; to the map<\/a>. The map point is essentially a &#8220;graph node&#8221; which refers to a Room. Another test <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/0ac2ec4265ceb2829123ae19bce6e174fd282b9e\">adds ConnectTo functionality<\/a> to represent &#8220;edges&#8221; of the graph. The edges are described in simple terms, using a <code>string<\/code> (e.g. <code>\"north\"<\/code>) representing a direction of travel to get to the target point. The next big piece is <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/868c98118e7abec7666be6067ccd5fc5d6c3244d\">adding <code>Start<\/code> and <code>Go<\/code> methods<\/a> to allow room travel. This change requires a new concept in Room which is represented by the <code>Enter<\/code> and <code>Leave<\/code> methods. The idea is that entering will activate all the functionality within a room (e.g. by subscribing to the verb handlers) and leave will deactivate (e.g. unsubscribe\/unregister). This is used in favor of the Dispose pattern because logically a Room still lives on even if you are not currently standing inside it.<\/p>\n<p>After handling several error cases (e.g. <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/f7efa7ec5735126176b8dc4229ce41b40617d8a3\">Start called twice<\/a>, <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/1b6a4161d541ed5b68839e9a3f2cee665c29a8bd\">ConnectTo when already connected<\/a>, etc.), I am ready to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/2dc91fb2ad1c97c139aecfbcc90fe129aa43e75a\">incorporate RoomMap into the sample game<\/a>. It&#8217;s fairly unremarkable right now because there is only one room.<\/p>\n<p>I still have some time, so I work on <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/96bed570261668b6536ef881e2439321f56ad62d\">improving the <code>RoomMap.Point<\/code> interface to disallow directly calling some of the infrastructure methods<\/a>. I achieve this with a private interface implementation &#8212; a rarely needed feature in my experience but a pretty good use case for this situation.<\/p>\n<p>A few changes later and I realize that <code>Go<\/code> should not be directly exposed as a public method. Otherwise, I will have to pass the RoomMap around in an unnatural way to the Rooms themselves. I need to remind myself to instead keep wearing my message-passing hat. So I <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/8f63cf57ada026551265d4396ca2213eba6f7c6b\">reimplement Go as a private method which handles the <code>GoMessage<\/code><\/a>. Now anyone can send the <code>GoMessage<\/code> without worrying about who will respond; loose coupling achievement unlocked!<\/p>\n<h2>Day 13<\/h2>\n<p>On this day, I want to focus on items. Any self-respecting adventure game allows the user to interact with items in the world. I start with some <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/add79b3869d3b36b4becc3b8345169a30e39ef0f\">minor cleanup around the unknown look case<\/a>. (I don&#8217;t want the error message to give away any clues about items that the game understands but has not revealed yet.) Then I dive right into <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/add79b3869d3b36b4becc3b8345169a30e39ef0f\">one of the fundamental item verbs &#8212; <code>Take<\/code><\/a>. I proceed like I did with <code>Look<\/code>, first handling <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/7dee57a44f58a17bc7ff5ce39728bb06d468b305\">the unknown case and then <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/b630261ca255feeb89158b2aaa2175c0adf61090\">the custom case<\/a>. Then I <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/e2f027d7c336a781bbb2dc9e5980123b158f9028\">implement &#8216;take&#8217; handling in the sample game<\/a>.<\/p>\n<p>Now I&#8217;m ready to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/18507c2ce2f91aeee1b1bb7c80f86a204525f770\">create the <code>Item<\/code> class and its first class collection <code>Items<\/code>, starting with one basic test<\/a>. Many tests later, I go <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/0b0af5bcedee58f21cc844988039ba5d04bc40d0\">back to the sample game and add a move command<\/a>. This command will be used with the &#8216;table&#8217; to reveal a hidden item, the &#8216;coin.&#8217; Of course, this feature is no good if I can&#8217;t actually drop items in a Room, so <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/9cf7a8331b6b7c32e800bac85e04e9f0c26dba34\">I work on the Drop command<\/a> which interacts with the newly added <code>Items<\/code> field in <code>Room<\/code>. Finally, I can <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/cfb9273ec35b9aad8deaa4db0ac0a380406d9651\">add <code>Coin<\/code><\/a>, the first custom item to my sample game.<\/p>\n<h2>Day 14<\/h2>\n<p>I notice that the <code>LookAround<\/code> functionality of <code>Room<\/code> is not to my liking. It relies on external enumeration of the <code>Items<\/code> collection. Let&#8217;s maintain encapsulation and instead shift this to a <a href=\"http:\/\/rubyblog.pro\/2016\/09\/tell-dont-ask-principle\">tell-don&#8217;t-ask<\/a> style. To prepare for this I first <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/518801bb85484ba97bf8f9356de4a4d1739c9322\">ensure <code>MessageBus<\/code> is passed to <code>Items<\/code><\/a>. Then it&#8217;s a simple matter of <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/d67b813d6450c9fcf676a69620640461a9425ddd\">removing the enumerator and handling <code>Look<\/code> directly<\/a>, using the reference to <code>MessageBus<\/code> to send output messages.<\/p>\n<p>Next up: <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/07ca3a821119f8282a02006d5820a506c1e72910\">handling custom actions for items<\/a>. The general idea here is that we want <code>Items<\/code> to be notified when the user sends a command, so that it can redirect it whenever the noun part matches an item in the list. To achieve this, we need to <code>Activate<\/code> the <code>Items<\/code> instance so that it can receive commands. (The reasoning behind this will become clear in a minute.) To complete this feature, we must <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/89c5696ec5e82e679331a630659caf720e44c967\">implement behavior to skip the action if the item is not recognized<\/a> and <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/da1b9e9ca1fe0116630dcb5773e952ed3d87a3ee\">make sure the message is consumed (by returning <code>true<\/code>)<\/a> but <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/34784a168a3c60755e3c89ccebb0326d844b8a42\">only if the action ends up being processed<\/a>. Of course, we need to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/9d5429b2711742c49e6ba6644b8f5a8e0d0c39a9\">allow the <code>Item<\/code> to tell us if the action is understood<\/a>, otherwise it will prevent later processing of this unknown message. In fact, the <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/8aee0a11653e85e06a4c62add679729772faacff\">default behavior of an <code>Item<\/code> should be to <em>not<\/em> handle custom actions<\/a> &#8212; it&#8217;s an opt-in feature.<\/p>\n<p>Now to flesh out the activation\/deactivation concept. This is necessary because every <code>Room<\/code> has its own <code>Items<\/code>, but the user can only be present in one <code>Room<\/code> at a time. We would not want <code>Room<\/code> X&#8217;s <code>Items<\/code> to remain &#8220;in scope&#8221; so to speak after leaving <code>Room<\/code> X and entering <code>Room<\/code> Y. To prepare for this new state, we need to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/1629f115d08d55e2b1fff365250eeeaa14d4926b\">make sure that <code>Items<\/code> will not respond to commands before <code>Activate<\/code><\/a>, <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/560db1f611ab46e69fefcde6016f5ff69701d133\">nor will it do so after <code>Deactivate<\/code><\/a>. Statefulness means more ways to go wrong, so we need to handle the various error cases like <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/fdb067b37dea007e4afc658716109b6cc7e5b3dc\"><code>Activate<\/code> twice<\/a>, <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/641d234543a3cf1387fa98233f09598ad878791a\"><code>Deactivate<\/code> twice<\/a>, and <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/a1d848db2b169de35c6a291940ec2324947d69cf\"><code>Deactivate<\/code> before <code>Activate<\/code><\/a>.<\/p>\n<p>After a brief interlude to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/b4a64370bc725ececf7ef65ae8686c03d4833dfc\">promote <code>Room.Drop<\/code> from <code>protected<\/code> to <code>public<\/code><\/a>, let&#8217;s <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/c3ad392f179f001afa6dc9f428e3f7f231fd866c\">start building interactions with <code>Items<\/code> via the <code>Room<\/code><\/a>. As discussed earlier, the main mechanism here is calling <code>Activate<\/code> on <code>Enter<\/code>ing the room. Of course, we can&#8217;t forget to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/7557529cae038d8056dd9f042d71d87ee54d884c\"><code>Deactivate<\/code> when we <code>Leave<\/code><\/a>.<\/p>\n<p>Before I end the day, I want to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/0396f7787d5548106be9a9ff5de9c39f0c93340f\">make one small tweak to the unknown verb error message<\/a>. Now that we support custom actions, it might be too revealing if we have different errors for completely unknown actions (e.g. &#8220;frazzle thingamajig&#8221;) vs. understood but unsupported actions (e.g. &#8220;drop table&#8221;). Instead we&#8217;ll just be noncommittal and say, &#8220;You can&#8217;t do that.&#8221; As a last step, <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/4b268f820cc0e9ed961398702578c04558a24015\">implement <code>Look<\/code> for individual items<\/a>, so that the user can get a more detailed description of the objects in the game.<\/p>\n<h2>Day 15<\/h2>\n<p>Now that we have the ability to look at items, let&#8217;s <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/563877c43d9cbe6e51a243763844f5c4c0e8a35a\">describe <code>Coin<\/code> in the sample game<\/a>. And remember that table in the middle of the room? Let&#8217;s <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/336e3996515ce38e7e1df17465f68c1be86deb90\">turn it into a full-fledged <code>Table<\/code> class<\/a>, deriving from <code>Item<\/code>. The game is getting more object-oriented by the minute!<\/p>\n<p>For the next big feature, let&#8217;s <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/d74cbb96b3c238d8df99222111c8ffd462b232c7\">start working on <code>Inventory<\/code><\/a>, specifically the ability to show the inventory via the <code>InventoryRequestedMessage<\/code>. Many games support the <a href=\"https:\/\/www.giantbomb.com\/inventory\/3015-513\/\">concept of an inventory<\/a> (i.e. the items the player currently has on hand) and the text adventure is no exception. Since <code>Inventory<\/code>, like <code>Room<\/code> before it, uses the <code>Items<\/code> class, we want to take advantage of all the functionality it has. However, showing your inventory is different than listing the contents of a room. For one thing, when you display your inventory, it should say something like, &#8220;You are carrying: (SOME ITEM)&#8221; instead of, &#8220;There is (SOME ITEM) here.&#8221; Let&#8217;s address this by <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/040acd472e7d8aa1117297d5ce2d4cd806a5a9c2\">using a caller-supplied format string for <code>Look<\/code><\/a>. It would also be nice if it printed a special message when you are carrying nothing instead just an empty string, so let&#8217;s <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/cbc993828f0c7516baa786c26d8902e61b1f2005\">return the count of items from the <code>Look<\/code> method<\/a>. Now we can <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/05d5ab7643be4cc41c3068956cc67cd7b767b94a\">implement the show inventory feature<\/a> (making sure we also <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/6313494614a24ed8003b6d0337e790041ca3bf8e\">properly unsubscribe after <code>Dispose<\/code><\/a>).<\/p>\n<p>To allow interacting with items in the <code>Inventory<\/code> we need to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/e7a61457f12aabe065b4097196676a01cf88266d\">implement custom action handling<\/a> just like we did in <code>Room<\/code>. Since the user&#8217;s main interaction point is still the <code>Room<\/code>, we need to <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/a18adda03f02279d6716dc958bf15c8936b7924a\">complete the protocol between <code>Room<\/code> and <code>Inventory<\/code> to show the user&#8217;s items<\/a>; the <code>Inventory<\/code> method in <code>Room<\/code> thus sends the <code>InventoryRequestedMessage<\/code> for which we already implemented the response above. Now we can <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/e559413fdec635e522e1d16edb9c6e861bd5ede8\">initialize Inventory in the sample game<\/a>, though it won&#8217;t do much yet.<\/p>\n<p>As yet, the user cannot add items to the inventory. Let&#8217;s change this by <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/29efebf19c841ebf61b1bc30427d2304a5f57815\">implementing the <code>Take<\/code> command in <code>Room<\/code><\/a>; so far, it just sends the <code>InventoryAddedMessage<\/code> which we expect to be handled elsewhere. The <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/121e227b53ead4109ea1e2c3b49d17abc7b07740\">inventory side of this equation comes next<\/a>, which wires up the <code>Inventory.Add<\/code> method to this message. Of course, not all items are obtainable. We need a way for each <code>Item<\/code> to choose whether it can be taken by <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/0623f9b13e2437948edd5a02001fa1661cff8863\">giving the option of overriding a TakeCore method<\/a>. Now the sample game can show examples of both cases via <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/a16d19e7c8f097c4b176b32916ee36e8ad86350b\">the coin which can be picked up<\/a> and <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/bd55ac473f7abeccfa4da8be034c3d26a60c2080\">the table which purports to be too heavy<\/a>. One final feature addition to the game shows a use case for overriding the take method &#8212; detecting whether the item has been picked up or not, to decide how to respond to a verb. Here we have a <a href=\"https:\/\/github.com\/brian-dot-net\/AdventureGame\/commit\/c27ff5ce4727008f6f6bfa1e76b725e8d2264e1e\">&#8220;read coin&#8221; command which only works if you are holding the item<\/a>.<\/p>\n<p>As of now, the game has the potential of handling multiple rooms in a map and multiple items in a room. The user can also interact with items in the world and even pick them up. It&#8217;s all coming together.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I last left off on Day 8 of my adventure game project. We continue from Day 9 today. Day 9 After warming up with a simple rename, I decide I don&#8217;t like how TextConsole and InputLoop interact. If I want&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[91,41],"tags":[],"class_list":["post-5603","post","type-post","status-publish","format-standard","hentry","category-design","category-tdd"],"_links":{"self":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/5603","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5603"}],"version-history":[{"count":3,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/5603\/revisions"}],"predecessor-version":[{"id":5608,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/5603\/revisions\/5608"}],"wp:attachment":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5603"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5603"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5603"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}