{"id":183,"date":"2015-03-17T10:37:21","date_gmt":"2015-03-17T18:37:21","guid":{"rendered":"http:\/\/adamantyr.com\/blog\/?p=183"},"modified":"2015-03-17T10:37:21","modified_gmt":"2015-03-17T18:37:21","slug":"transacting-scripts","status":"publish","type":"post","link":"http:\/\/www.adamantyr.com\/index.php\/2015\/03\/17\/transacting-scripts\/","title":{"rendered":"Transacting Scripts"},"content":{"rendered":"<p>My focus remains on turning out a working and complete demo of the game&#8230; I&#8217;ve written a bunch of code I haven&#8217;t even had a chance to test yet. And I&#8217;m currently working on plotting out a long-neglected portion of the game; complex transactions with NPC&#8217;s.<\/p>\n<p>I&#8217;m doing SOME stuff that isn&#8217;t entirely practical. For example, I&#8217;m finally working on finishing the title screen. I had always been stymied by the fact I didn&#8217;t really want to take the time to plot out the thing in a paint program. (ESPECIALLY in TI-Artist, which is incredibly painful to use for pixel plotting. Multi-color mode, blech!) I finally found a low-tech sneaky way to do it&#8230; Transcribe the character graphics myself by the naked eye into the bit patterns and hex-edit them into a Paint N&#8217;Print file. (Paint N&#8217;Print is my favorite editor; the zoom mode is perfect!) I can then colorize it later in the paint program.<\/p>\n<p>So, about those transactions&#8230;<\/p>\n<p>I decided early on not to have a text parser in the game. (Basically, a cursor which would allow you to enter key words.) My decision was based upon two things:<\/p>\n<ol>\n<li>Text parsers are a pain to implement and error check in assembly language<\/li>\n<li>Too much like Ultima<\/li>\n<\/ol>\n<p>How can being like Ultima be bad? Well, Ultima IV is actually very simplistic; there is a maximum of 32 NPC&#8217;s in each town, and each one has a single 288 byte record to store all their conversations. (Except for special NPC&#8217;s like Lord British and Hawkwind, of course.) If you look, the actual depth of each character is shallow; each character only has two potential keywords beyond the baselines (name, job, health) and a single question and virtue that is affected by it. Ultima V is slightly more complicated with the day and night cycles and NPC schedules, but conversations are largely the same structure.<\/p>\n<p>Also, there&#8217;s a certain degree of &#8220;I want this to be MY game, not just a copy of Ultima.&#8221; There&#8217;s been too poor-man copies of Ultima over the years (<em>Gates of Delirium<\/em> comes to mind&#8230;) and I want my game to stand out as something that is entirely itself.<\/p>\n<p>Another aspect of my design is, I want the game world to CHANGE based on the player&#8217;s actions. All too many old CRPG&#8217;s have worlds that largely remain the same, even after the player has accomplished things. You save the town and they&#8217;re STILL talking about the danger?<\/p>\n<p>So, there are two kinds of NPC&#8217;s in the game, simple and complex. The simple ones are much like the NPC&#8217;s in Ultima III; they have a single response they say and nothing more. There will also be map flags for each area so that if you have achieved certain goals, they say different things.<\/p>\n<p>Complex NPC&#8217;s though, are another matter. For those, I&#8217;ve had to create my own little scripting language.<\/p>\n<p>Essentially, each complex NPC has a set of local flags (one byte&#8217;s worth, one of which is always the &#8220;visited\/revisited&#8221; flag) and a set of transaction records, each one word (16-bit) long. If the average length of these transactions ends up being a consistent size I may just convert them to longer records and live with a little wasted space.<\/p>\n<p>Each word has a code indicating either an action or a query, with a variant amount of data after it. For example, it may check that a certain flag is set. If so, it moves to the appropriate spot in the transaction string using a positive\/negative offset value, and continues transaction processing from there. It can display messages, set up options for the player to select from a list to determine a series of next results. And it can give money (or take it), items, or make changes to the party and player data as needed. A veritable transaction engine!<\/p>\n<p>Here&#8217;s an example of how it may look:<\/p>\n<pre>TRANSACTION\n\nOPEN:\nIF Visited_Flag\u00a0\u00a0 \u00a0(4)\n\u00a0\u00a0 \u00a0DISPLAY Intro (4)\n\u00a0\u00a0 \u00a0SET Visited_Flag (2)\n\u00a0\u00a0 \u00a0BRANCH Options (2)\nELSE\n\u00a0\u00a0 \u00a0DISPLAY Revisit (4)\n\u00a0\u00a0 \u00a0BRANCH Options (2)\nOPTIONS:\n\u00a0\u00a0 \u00a0OPTION Question_1, Question_2 (10)\n\u00a0\u00a0 \u00a0SELECT Option (2)\n\u00a0\u00a0 \u00a0IF Option_1\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0DISPLAY Read_1, Read_2 (6)\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0BRANCH OPEN (2)\n\u00a0\u00a0 \u00a0IF Option_2\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0DISPLAY Take_1 (4)\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0SET Quest_Item_0 (2)\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0CLEAR Mob (12)\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0END Transaction (2)\n\nTotal: 58 bytes (29 words)<\/pre>\n<p>In fact, as I was designing the system, I realized that I could use it to replace some things in game. For example, I originally had fountains as a stock object in game for dungeons and places, that would have variant effects upon you. But I&#8217;ve been leaning towards removing them as a more &#8220;gamey&#8221; object more appropriate to old-school first-person dungeon designs, and I realized that I didn&#8217;t even need to HAVE special code for them. I can just make a fountain a transaction if I still want one!<\/p>\n<p>I did briefly consider integrating shopkeepers into the same transaction system, since it&#8217;s already going to be doing a lot of heavy lifting. I decided against it in the end, though, because with shopkeepers, I have much more predictable data structures. That will let me write much more streamlined code to handle the transactions for those.<\/p>\n<p>The only pain point with this approach is that coding the actual scripts up is going to be a pain. Since all the offsets are going to be localized and fixed, that means they will need to be updated with any changes. I&#8217;m going to initially try and set up an Excel spreadsheet to store this for me so I can (hopefully) just copy out a clean hex string to paste, but we&#8217;ll see how it goes&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My focus remains on turning out a working and complete demo of the game&#8230; I&#8217;ve written a bunch of code I haven&#8217;t even had a chance to test yet. And I&#8217;m currently working on plotting out a long-neglected portion of &hellip; <a href=\"http:\/\/www.adamantyr.com\/index.php\/2015\/03\/17\/transacting-scripts\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,4,5,12],"tags":[],"class_list":["post-183","post","type-post","status-publish","format-standard","hentry","category-coding","category-crpg","category-design","category-ti-994a"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pgaeMJ-2X","_links":{"self":[{"href":"http:\/\/www.adamantyr.com\/index.php\/wp-json\/wp\/v2\/posts\/183","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.adamantyr.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.adamantyr.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.adamantyr.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.adamantyr.com\/index.php\/wp-json\/wp\/v2\/comments?post=183"}],"version-history":[{"count":0,"href":"http:\/\/www.adamantyr.com\/index.php\/wp-json\/wp\/v2\/posts\/183\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.adamantyr.com\/index.php\/wp-json\/wp\/v2\/media?parent=183"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.adamantyr.com\/index.php\/wp-json\/wp\/v2\/categories?post=183"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.adamantyr.com\/index.php\/wp-json\/wp\/v2\/tags?post=183"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}