<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Nolithius.com</title>
	<atom:link href="http://www.nolithius.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.nolithius.com</link>
	<description>Home of Ebyan Alvarez-Buylla</description>
	<lastBuildDate>Tue, 28 Dec 2021 23:40:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.5</generator>
	<item>
		<title>Organization XIII Name Generator</title>
		<link>http://www.nolithius.com/articles/procedural-generation/organization-xiii-name-generator</link>
					<comments>http://www.nolithius.com/articles/procedural-generation/organization-xiii-name-generator#respond</comments>
		
		<dc:creator><![CDATA[Ebyan Alvarez-Buylla]]></dc:creator>
		<pubDate>Tue, 28 Dec 2021 23:35:58 +0000</pubDate>
				<category><![CDATA[Procedural Generation]]></category>
		<guid isPermaLink="false">http://www.nolithius.com/?p=2218</guid>

					<description><![CDATA[I built this little tool after listening to Waypoint Radio&#8217;s Kingdom Hearts Lore Reasons episodes. I must admit I have not played any of the Kingdom Hearts games but I could not help myself to put together yet another name generator! A what name generator? From my very limited understanding, members of Organization 13 in [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I built <a href="/x">this little tool</a> after listening to <a href="http://www.waypoint.zone" target="_blank" rel="noopener noreferrer">Waypoint Radio&#8217;s</a> <em>Kingdom Hearts</em> <a href="https://www.vice.com/en/topic/lore-reasons" target="_blank" rel="noopener noreferrer">Lore Reasons</a> episodes. I must admit I have not played any of the <em>Kingdom Hearts</em> games but I could not help myself to put together yet another name generator!<span id="more-2218"></span></p>
<p><iframe loading="lazy" src="http://www.nolithius.com/x" border="0" style="border:none;" width="640" height="540"></iframe></p>
<h4>A <em>what</em> name generator?</h4>
<p>From my very limited understanding, members of Organization 13 in the <em>Kingdom Hearts</em> games have names formed from anagrams of their original names plus the letter X. As you might imagine, there are already a number of such generators out there, but they have a number of problems that I wanted to tackle:</p>
<ol>
<li>They are non-deterministic.</li>
<li>They do not calculate all of the possible permutations.</li>
<li>They cannot guarantee &#8220;the best&#8221; generated names.</li>
</ol>
<p>Normally, when putting together a name generator, these tend to be non-issues. Of course you want non-determinism to get different sets of names each time, a non-exhaustive subset of all possibilities for speed and practicality, and a spectrum of different quality names&mdash; that is, however you measure quality, you might desire some amount of deviation to add flavor and variety.</p>
<p>However, this particular type of name generator begs for, if not one best-and-final result, at least a sorted, scored list from which you can pick your favorite. Therefore, we must not only calculate all possible permutations of name+X, but also do our best to encourage the best results to rise to the top.</p>
<h4>Permuting</h4>
<p>I worked out this simple permutation algorithm by visualizing colored marbles being drawn from a bag. Not a great visual, mind you, seeing as we need the letters in a deterministic order each time and random drawing from bags best informs an entirely different class of algorithms, but I digress.</p>
<p>We begin by stepping through each letter and adding it to the results; then, before moving on to the next letter, we select the next letter and add it to every position of every previous result, and repeat this last step until all letters have been exhausted. As you can imagine, performance blows up quite exponentially with regards to the string size, and there is a lot of wasted sub-anagram results which we don&#8217;t use but could conceivably be useful in a different context.</p>
<p>Say you have a name &#8220;ABC&#8221; and you want to find all possible permutations. Step through every letter and add it first to the list of results, then to every position of every existing result on the list. The sequence will look like this:</p>
<pre>
A   // The list is empty at this point, so just add A and done.
B   // Onto B. First add it to the list.
BA  // Then add it to every position of every item on the list.
AB
C   // Onto C.
CA  // Add to every position of every item on the list.
AC
CB
BC
<strong>CBA // Finally we start building some actual results! 
BCA
BAC
CAB
ACB
ABC</strong>
</pre>
<p>There are a number of improvements that can be made to this algorithm if we only care about full anagrams. Firstly, you might&#8217;ve noticed that the results right before our final 3-letter results&mdash; all non-3-letter results with the letter C&mdash; don&#8217;t go on to later be built upon by other letters, and can therefore be omitted. Secondly, you might notice that the lone B is guaranteed to never &#8220;fill out&#8221; to full size. Generally speaking: <strong>existing results with <tt>length < i</tt> are guaranteed to never build up to a full length result, and therefore can be skipped.</strong> In practice, that means that:</p>
<ol>
<li> The only letter that needs to be added by itself is the first one and
<li> At every insertion step, only bother inserting into results that are of the largest size, which are the only ones that will end up yielding full-length anagrams.</li>
</ol>
<p>The sequence therefore becomes:</p>
<pre>
A   // A is the only item added to the empty list.
BA  // B is operating upon the largest items on the list.
AB
<strong>CBA // C is operating only upon he largest items as well.
BCA
BAC
CAB
ACB
ABC</strong>
</pre>
<p>It might not seem like much for a 3-letter example, but given the nature of these exhaustive permutations, it can save you hundreds of thousands of useless results with 8 or 9-letter names!</p>
<h4>Scoring</h4>
<p>Now that we have a list of all possible permutations, we could just as well display them all to the user and allow them to choose their favorite. However, a little bit of creative scoring can go a long way. First, we deploy some basic safeguards to cull the worst options:</p>
<ol>
<li>Don't even bother with "Xname" and "NameX". Boring, just cut them out.</li>
<li>Give a low score, but still allow, names with 4-non-y-consonant sequences.</li>
</ol>
<p>Now the more interesting scoring work begins. The base scorer does the following:</p>
<p>Given a list of 1000+ common words and 1000+ common names, as well as all of the canon Organization XII names, of course, extract all substring fragments of a given length. For every position in the word being scored, compare the next letters of that length against the list of fragments&mdash; paying special attention to the first and last fragment&mdash; and give the word +1 point if the fragment is found, with additional points if the fragment is at the beginning or end. (It all sounds a lot more complicated than it is). Here's a very barebones example:</p>
<p>Let's say the blessed list of names and words is <tt><strong>["Steven", "Hello"]</strong></tt>. For the scorer with length 3 (there are three separate scorers of length 3, 4, and 5 to capture both general and specific word structure), the following fragments are extracted:</p>
<pre>
<strong>Ste</strong>
tev
eve
ven
<strong>en.</strong>
<strong>Hel</strong>
ell
llo
<strong>lo.</strong>
</pre>
<p>The emphasized fragments, as you can see, capture the beginning of the word as well as the end with the added terminal character (which can be anything, really, but a "." seemed fitting).</p>
<p>Using these fragments, a name like "Heltevx" would receive +3 points for a beginning fragment <strong>"Hel"</strong>, none for "elt", none for "lte", +1 for <strong>"tev"</strong>, none for "evx", and none for "vx.", for a total of 4 points.</p>
<p>However, a name like <strong>Heltevx</strong> is not very good. We can expand our source words/names for scoring to naturally bury it as other better quality names rise to the top, <em>or</em> we can explicitly guard against what makes this name low quality: the "vx" terminal is awkward. To that end, we must put together an imperfect but good-enough list of low quality starting substrings and ending substrings to score negatively. These include awkward consonant combinations, such as "Xb" and "Bx", but allow the esoteric-but-plausible "Xh", for example.</p>
<p>That's pretty much it! All of these details might seem old hat to you if you're familiar with name generators, but I certainly hope they've cleared up some mysteries for you if you're not! Have a look at <a href="/x">the generator in action</a> and the source code <a href="https://github.com/Nolithius/organization13" target="_blank" rel="noopener noreferrer">on GitHub</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.nolithius.com/articles/procedural-generation/organization-xiii-name-generator/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Blogs are Back and so is Textmode!</title>
		<link>http://www.nolithius.com/updates/etc/blogs-are-back-and-so-is-textmode</link>
					<comments>http://www.nolithius.com/updates/etc/blogs-are-back-and-so-is-textmode#respond</comments>
		
		<dc:creator><![CDATA[Ebyan Alvarez-Buylla]]></dc:creator>
		<pubDate>Sat, 23 Jan 2021 02:12:49 +0000</pubDate>
				<category><![CDATA[Etc]]></category>
		<guid isPermaLink="false">http://www.nolithius.com/?p=2178</guid>

					<description><![CDATA[Ok. So I lied about blogs. They&#8217;re still dead. Also, did you hear about Flash? A shame that. Truly an end to an era. Textmode, ASCII art, PETSCII art, etc., however, is having a bit of a moment in the sun and you know I&#8217;m into it. Let&#8217;s catch up on the last couple of [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Ok. So I lied about blogs. They&#8217;re still dead. Also, did you hear about Flash? A shame that. Truly an end to an era.</p>
<p><a href="https://www.reddit.com/r/textmode/" target="_blank" rel="noopener noreferrer">Textmode</a>, ASCII art, PETSCII art, etc., however, is having a bit of a moment in the sun and you know I&#8217;m into it. Let&#8217;s catch up on the last couple of years of blog silence.<span id="more-2178"></span></p>
<h4>Flash is Dead for Real This Time</h4>
<p>I&#8217;m still salty about Flash being killed. It&#8217;s highly unlikely I&#8217;ll rework all of the projects on this site to JavaScript, though any new projects and demos will be HTML5. I&#8217;ll have to make some time to go through the process of deleting (what us in the biz call &#8220;sunsetting&#8221;) the games that now essentially deliver dead plug-in shells.</p>
<h4>Blogs are Dead But You Can Still Read Them</h4>
<p>Do you remember when the Internet felt like something everyone owned, and no one owned? This weird, both sprawling and intimate agglomeration of odd sites and fledgling platforms. And now those platforms have fledged and taken flight and we are cast in their shadow. Google decides Reader is no longer a fun project for them, they kill it. Adobe decides Flash is ash, they not only discontinue it, they outright retroactively block it. Who does that? Megalomaniacs, that&#8217;s who.</p>
<h4>Textmode</h4>
<p>It should come as no surprise that I&#8217;m <a href="http://www.nolithius.com/updates/etc/beautiful-ascii-art-and-roguelike-concept-screens">a fan</a> of this ancient art form. Only I didn&#8217;t know of its origins or of <a href="https://demozoo.org/graphics/273260/" target="_blank" rel="noopener noreferrer">PETSCII</a><a href="https://www.instagram.com/p/Ba2PYqhHjpb/" target="_blank" rel="noopener noreferrer">&#8211;</a><a href="https://www.instagram.com/p/B7v7-uwB9cz/" target="_blank" rel="noopener noreferrer">based</a> <a href="http://www.raquelmeyers.com" target="_blank" rel="noopener noreferrer">art</a> or what can more generally be described as Textmode art.</p>
<p>I tried to get into doing my own textmode stuff before, but it turns out alls I needed was an editor with the ability to rotate and flip tiles (don&#8217;t tell the purists). Enter <a href="http://vectorpoem.com/playscii/" target="_blank" rel="noopener noreferrer">Playscii</a>, which also has great support for custom tile sets, palettes, animations, and even tile sets with more than 256 glyphs (also don&#8217;t tell the purists).</p>
<h4>Here are Some Things I&#8217;m Working On</h4>
<p>This is a thing:</p>
<div><img src="/wp-content/uploads/2021/01/005_tps_sonya.png" style="display:block; margin:0 auto; padding-bottom:18px"></div>
<p>This is another thing:</p>
<div style="overflow:hidden; width:1008px; position:relative; left:-24px; padding-bottom:18px">
<img src="/wp-content/uploads/2021/01/Codex_0002.png" style="float:left; display:block"><img src="/wp-content/uploads/2021/01/Codex_0004.png" style="float:left; display:block"><img src="/wp-content/uploads/2021/01/Codex_0007.png" style="float:left; display:block">
</div>
<p>(more on these soon)</p>
<h4>Guildmaster?</h4>
<p>The short of it: <em>paused</em>.</p>
<p>The long of it: I spent quite a long time on world generation, UI design, and even name generation, but never quite got the core loop of the game to be something I was happy with. I started down the path of a large design restructure and simplification but it&#8217;s been hard to stay motivated on a long-form project this past year. I did pick up ukulele, electric guitar, and am <a href="https://www.instagram.com/ebyanalvarezbuylla/" target="_blank" rel="noopener noreferrer">gardening</a> a lot more!</p>
<h4>Nolithius in 2021</h4>
<p>Could be an unofficial new year&#8217;s resolution or a result of Flash having finally been killed or a growing disillusion with social media or a re-broadening of interests partly brought upon by the pandemic <em>but in any case</em> I have resolved to accomplish the following in 2021:</p>
<ul>
<li>Blog more</li>
<li>Release a new game</li>
<li>Restructure Guildmaster</li>
<li>Get good at music</li>
<li>Garden more</li>
</ul>
<p>Cheers!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.nolithius.com/updates/etc/blogs-are-back-and-so-is-textmode/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>World Generation Techniques: Domain Warping</title>
		<link>http://www.nolithius.com/articles/world-generation/world-generation-techniques-domain-warping</link>
					<comments>http://www.nolithius.com/articles/world-generation/world-generation-techniques-domain-warping#respond</comments>
		
		<dc:creator><![CDATA[Ebyan Alvarez-Buylla]]></dc:creator>
		<pubDate>Sat, 03 Mar 2018 23:55:35 +0000</pubDate>
				<category><![CDATA[World Generation]]></category>
		<guid isPermaLink="false">http://www.nolithius.com/?p=2074</guid>

					<description><![CDATA[Domain Warping, domain distortion, or noise distortion is an effective technique to breathe additional life into noise maps by stretching and twisting them about, adding some excitement to the otherwise fairly uniform underlying noise. We’ll demonstrate this technique by starting with a vanilla Perlin noise map as the base, and displacing its positions along two [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><em>Domain Warping</em>, <em>domain distortion</em>, or <em>noise distortion</em> is an effective technique to breathe additional life into noise maps by stretching and twisting them about, adding some excitement to the otherwise fairly uniform underlying noise.</p>
<p>We’ll demonstrate this technique by starting with a vanilla Perlin noise map as the base, and displacing its positions along two sets of Perlin noise maps to achieve a sum greater than its parts. Let’s dive right in:<span id="more-2074"></span></p>
<h4>The Base Map</h4>
<p>Start with a Perlin noise map that fits your needs. Play around with the map size and noise parameters until you are satisfied. Due to the nature of the displacement, it is useful to start with a map that is tileable both vertically and horizontally, since points will almost certainly be displaced off of the map boundaries and will need to be wrapped around.</p>
<p><embed src="/wp-content/uploads/2018/03/domain_warping_demo_1.swf" allowfullscreen="false" allowscriptaccess="always" style="width: 480px; height: 580px; margin: 0 auto; display:block;"></p>
<h4>Warp 20: Engage</h4>
<p>We’ll need to generate two additional Perlin noise maps for displacement: one for the X values, and one for the Y. These should also be tileable to avoid any obvious seams across map boundaries, and each cell should have a value ranging from -1 to 1. If they have a value from 0 to 255, as in the ones in the demo, map them to the -1 to 1 range with the necessary arithmetic (<tt>x / 255 * 2 - 1</tt>, in this case).</p>
<p>The one missing ingredient is the amplitude. This describes the maximum displacement that will occur for a value of -1 or 1. Pick a reasonable value for your purposes: from 1 to twice your map dimensions. For this demo I’ve chosen 20.</p>
<p>Now we warp:</p>
<ul>
<li>Iterate through each x/y value.</li>
<li>For each position, grab the corresponding value from the X displacement map and multiply it times the amplitude, and do the same for the Y displacement map.</li>
<li>You now have two values, one for X, and one for Y, in the range (-amplitude, amplitude).</li>
<li>These describe the x/y offset, from the current position, of the cell that will be replacing this cell in the result. So if we’re working with cell 5,10, and the offset values are -2, 9, we’ll write the value in cell 3, 19 to the result, at position 5, 10.</li>
<li>We must also ensure that we handle offsets that reach across map boundaries: for our purposes, wrapping works well, though clamping may also give you reasonable results.</li>
</ul>
<p><embed src="/wp-content/uploads/2018/03/domain_warping_demo_2.swf" allowfullscreen="false" allowscriptaccess="always" style="width: 960px; height: 580px; display:block; position: relative; left: -180px;"></p>
<p><strong>Note:</strong> I&#8217;ve chosen ranges for most values such that the demo produces satisfactory results. I encourage you to tinker with the <a href="http://www.github.com/nolithius/domainwarping" target="_blank">source code</a> such that you may explore what lies beyond these bounds!</p>
<h4>Tidying Things Up</h4>
<p>Depending on your particular needs, you may have all that you require as of this point. However, for our world generation purposes, we’ll take some additional steps to round out the edges of the map, pick a water line, and finally, assign some color values to different elevations so that we can better appreciate the difference domain warping makes.</p>
<p>For a quick rounding of the map’s edges, I recommend a simple gradient circle map, which multiplies values within an inner radius times 1, then linearly interpolates to 0 at the outer radius. (The keen observer may have noticed that I have moved away from the more interesting yet radically more expensive particle deposition map from <a href="http://www.nolithius.com/articles/world-generation/world-generation-breakdown">World Generation Breakdown</a>.)</p>
<p>To pick a water line, you may be inclined to take your max elevation after you’ve normalized your maps and multiply it times the desired water cover. However, collecting all of the map&#8217;s values in a sorted list, then indexing the value at <tt>water_line_percent * list.length</tt> will provide more accurate results, since the distribution of the noise values is unlikely to be linear. In the source code, the Map class provides a handy <tt>getElevationByPercentage()</tt> function for this purpose.</p>
<p><embed src="/wp-content/uploads/2018/03/domain_warping_demo_3.swf" allowfullscreen="false" allowscriptaccess="always" style="width: 960px; height: 580px; display:block; position: relative; left: -180px;"></p>
<p>I certainly hope to see more procedurally-generated worlds taking advantage of simple-yet-effective techniques such as domain warping. The source code for all of the demos, and of course, the underlying domain warp logic, can be found on <a href="http://www.github.com/nolithius/domainwarping" target="_blank">GitHub</a>. Enjoy!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.nolithius.com/articles/world-generation/world-generation-techniques-domain-warping/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Chronophase Source Code Released!</title>
		<link>http://www.nolithius.com/updates/chronophase-updates/chronophase-source-code-released</link>
					<comments>http://www.nolithius.com/updates/chronophase-updates/chronophase-source-code-released#respond</comments>
		
		<dc:creator><![CDATA[Ebyan Alvarez-Buylla]]></dc:creator>
		<pubDate>Sat, 29 Apr 2017 18:21:55 +0000</pubDate>
				<category><![CDATA[Chronophase]]></category>
		<category><![CDATA[Updates]]></category>
		<guid isPermaLink="false">http://www.nolithius.com/?p=2064</guid>

					<description><![CDATA[I recently had a request to release the Chronophase source code, which, after many years, still seems to hold up reasonably well! For the brave of heart, this is what the source code for a 4-day roguelike challenge looks like: https://github.com/Nolithius/chronophase. Full disclosure: Chronophase is not a traditional roguelike but rather a brief exploration of [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I recently had a request to release the <a href="/chronophase"><em>Chronophase</em></a> source code, which, after many years, still seems to hold up reasonably well!</p>
<p>For the brave of heart, this is what the source code for a <a href="http://www.roguebasin.com/index.php?title=4DRL_Contest_2010" target="_blank">4-day roguelike challenge</a> looks like: <a href="https://github.com/Nolithius/chronophase" target="_blank">https://github.com/Nolithius/chronophase</a>.<span id="more-2064"></span></p>
<p>Full disclosure: <em>Chronophase</em> is not a traditional roguelike but rather a brief exploration of what an ASCII turn-based space dogfighting game could be.</p>
<p>The original source was built with Flash and relied on an embedded asset in the FLA, so I took a little bit of time to rework it for IntelliJ IDEA and a standalone AIR SDK compile. It should be straightforward to bring it into Flash Develop or your preferred IDE.</p>
<p>Enjoy!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.nolithius.com/updates/chronophase-updates/chronophase-source-code-released/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Nolithius.com Fall Clean-Up</title>
		<link>http://www.nolithius.com/updates/etc/nolithius-com-fall-clean-up</link>
					<comments>http://www.nolithius.com/updates/etc/nolithius-com-fall-clean-up#respond</comments>
		
		<dc:creator><![CDATA[Ebyan Alvarez-Buylla]]></dc:creator>
		<pubDate>Fri, 14 Oct 2016 23:06:42 +0000</pubDate>
				<category><![CDATA[Etc]]></category>
		<guid isPermaLink="false">http://www.nolithius.com/?p=2054</guid>

					<description><![CDATA[It&#8217;s been a while since the site got some love, so I&#8217;ve taken a bit of time to make a few enhancements, mostly with the focus of separating evergreen content from timely updates. A rough list of the notable changes includes: New homepage layout. Games section, with game descriptions. About section, with a little information [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>It&#8217;s been a while since the site got some love, so I&#8217;ve taken a bit of time to make a few enhancements, mostly with the focus of separating evergreen content from timely updates. A rough list of the notable changes includes:<span id="more-2054"></span></p>
<ul>
<li>New homepage layout.</li>
<li><a href="/games">Games</a> section, with game descriptions.</li>
<li><a href="/#about">About</a> section, with a little information about yours truly.</li>
<li>Evergreen content now housed under <a href="/articles">Articles</a>.</li>
<li>Timely posts are now housed under <a href="/updates">Updates</a>.</li>
<li>Removed tags as a method of navigation.</li>
<li>Added redirects under the hood so old URLs still reach the expected content.</li>
<li>Removed old, less relevant posts.</li>
</ul>
<p>There are a series of enhancements I cut from this pass to keep on pace with the development of <em><a href="/guildmaster">Guildmaster</a></em>, but which I plan to tackle in the coming months, such as:</p>
<ul>
<li>Widening the readable area for the posts.</li>
<li>Moving the <a href="http://www.crossworddungeon.com" target="_blank">Crossword Dungeon microsite</a> to <a href="/crossword-dungeon">/crossword-dungeon</a>.</li>
<li>Adding the Guildmaster microsite to <a href="/guildmaster">/guildmaster</a>.</li>
<li>Cleaning up articles to free them of time-sensitive content</li>
<li>Organizing articles in more cohesive series. For example, instead of a monolithic post, splitting the topic of <a href="/world-generation/world-generation-breakdown">World Generation</a> into a shorter sequence of techniques you might employ together or a-la-carte.</li>
</ul>
<p>Nice to haves, but not must-haves!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.nolithius.com/updates/etc/nolithius-com-fall-clean-up/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>World Generation Breakdown</title>
		<link>http://www.nolithius.com/articles/world-generation/world-generation-breakdown</link>
					<comments>http://www.nolithius.com/articles/world-generation/world-generation-breakdown#comments</comments>
		
		<dc:creator><![CDATA[Ebyan Alvarez-Buylla]]></dc:creator>
		<pubDate>Sun, 20 Mar 2016 05:46:54 +0000</pubDate>
				<category><![CDATA[World Generation]]></category>
		<category><![CDATA[ascii]]></category>
		<category><![CDATA[dance of death]]></category>
		<category><![CDATA[procedural generation]]></category>
		<category><![CDATA[roguelike]]></category>
		<category><![CDATA[source code]]></category>
		<category><![CDATA[wilderness generation]]></category>
		<category><![CDATA[world generation]]></category>
		<guid isPermaLink="false">http://www.nolithius.com/?p=508</guid>

					<description><![CDATA[A large part of Dance of Death v0.6.136 was the addition of world generation. Although the world is little more than a large island at the moment, the results are rather satisfying, even considering that the current method of generating terrain is purely based on elevation. After experimenting with a number of techniques, I settled [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>A large part of <a href="http://www.nolithius.com/dod">Dance of Death</a> v0.6.136 was the addition of world generation. Although the world is little more than a large island at the moment, the results are rather satisfying, even considering that the current method of generating terrain is purely based on elevation. After experimenting with a number of techniques, I settled on this simple formula: 1) Generate Fractal Perlin Noise, 2) Multiply noise by a radial gradient, and 3) Apply terrain and water line. Here is the breakdown:<span id="more-508"></span></p>
<p>You can click on any of the images to view an interactive demo, and click again on the demo to generate a new map. The images were all generated randomly, so they do not correspond to a progression of the same maps (while Flash&#8217;s Perlin noise generator can be seeded, its random function cannot). Source code is available from <a href="http://code.google.com/p/dance-of-death-worldgen/" target="_blank">Google Code</a>, where you can grab it <a href="http://dance-of-death-worldgen.googlecode.com/svn/trunk/" target="_blank">directly from SVN</a>.</p>
<h4>Step 1: Generate Perlin Noise</h4>
<p>Generate a Fractal Grayscale Perlin Noise with an x-frequency of half the width, a y-frequency of half the height, and 8 octaves. For more loose islands, or for larger maps, you can drop the frequency to 1/4th of the width and height or lower, to fit your purposes. You can normalize the noise from 0-255 if you like, though normalizing now will become redundant later on. This is what we have so far:</p>
<div style="display:none">
<div id="demo1" style="width: 704px; height: 384px;"><embed src="/wp-content/uploads/2010/09/dodworldgen-noise-normalized.swf" allowfullscreen="false" allowscriptaccess="always" wmode="transparent" style="width: 704px; height: 384px;"></div>
<div id="demo2" style="width: 704px; height: 384px;"><embed src="/wp-content/uploads/2010/09/dodworldgen-noise-terrain.swf" allowfullscreen="false" allowscriptaccess="always" wmode="transparent" style="width: 704px; height: 384px;"></div>
<div id="demo3" style="width: 704px; height: 384px;"><embed src="/wp-content/uploads/2010/09/dodworldgen-rollingparticle-nobias.swf" allowfullscreen="false" allowscriptaccess="always" wmode="transparent" style="width: 704px; height: 384px;"></div>
<div id="demo4" style="width: 704px; height: 384px;"><embed src="/wp-content/uploads/2010/09/dodworldgen-rollingparticle-centerbias.swf" allowfullscreen="false" allowscriptaccess="always" wmode="transparent" style="width: 704px; height: 384px;"></div>
<div id="demo5" style="width: 704px; height: 384px;"><embed src="/wp-content/uploads/2010/09/dodworldgen-final-elevation.swf" allowfullscreen="false" allowscriptaccess="always" wmode="transparent" style="width: 704px; height: 384px;"></div>
<div id="demo6" style="width: 704px; height: 384px;"><embed src="/wp-content/uploads/2010/09/dodworldgen-final-terrain.swf" allowfullscreen="false" allowscriptaccess="always" wmode="transparent" style="width: 704px; height: 384px;"></div>
</div>
<p><a href="#demo1" class="thickbox clear" title="Grayscale Fractal Perlin Noise, normalized for contrast. Click to generate."><img src="/wp-content/uploads/2010/09/dodworldgen-noise-normalized.png" title="Grayscale Fractal Perlin Noise, normalized for contrast. Click to view demo." alt="Grayscale Fractal Perlin Noise, normalized for contrast. Click to view demo."><span class="caption">Grayscale Fractal Perlin Noise, normalized for contrast. Click to view demo.</span></a></p>
<p>If we apply the terrain to the tiles at this point, we&#8217;ll end up with something like this (<a href="#applying_terrain">jump ahead</a> for the terrain application method):</p>
<p><a href="#demo2" class="thickbox clear" title="Terrain applied to noise. Click to generate."><img src="/wp-content/uploads/2010/09/dodworldgen-noise-terrain.png" title="Terrain applied to noise. Looks pretty good, but it touches the edges and lacks an overall island look. Click to view demo." alt="Terrain applied to noise. Looks pretty good, but it touches the edges and lacks an overall island look. Click to view demo."><span class="caption">Terrain applied to noise. Looks pretty good, but it touches the edges and lacks an overall island look. Click to view demo.</span></a></p>
<h4>Step 2: Generate Rolling Particle Mask</h4>
<p>To get the island to be biased towards the center and avoid touching the edges, a straightforward solution is to multiply its values by a radial gradient mask ranging from 1 near the center, to 0 near the edges. A plain radial gradient might do the trick, since the Perlin noise already provides a healthy amount of randomness. However, I went with a modified version of the Rolling Particle algorithm to get some additional roughness. The basic algorithm goes something like this:</p>
<ul>
<li>Start with a blank map, all 0s.</li>
<li>Pick a random starting spot for the particle.</li>
<li>Increment the value on the map by 1 where the particle is located.</li>
<li>Move the particle to a random adjacent position whose value is less than or equal to the current position (imagine the particle rolling downhill).</li>
<li>Repeat the last 2 steps as long as the particle is alive.</li>
<li>Repeat for a large number of particles.</li>
</ul>
<p>A particle life of 50, with 3000 particles works well for this map size (which is 88&#215;32, by the way), experiment to get values that work for you. If we normalize, we get this: </p>
<p><a href="#demo3" class="thickbox clear" title="Basic Rolling Particle algorithm, 3000 iterations, particle life 50. Click to generate."><img src="/wp-content/uploads/2010/09/dodworldgen-rollingparticle-nobias.png" title="Basic Rolling Particle algorithm, 3000 iterations, particle life 50. Click to view demo." alt="Basic Rolling Particle algorithm, 3000 iterations, particle life 50. Click to view demo."><span class="caption">Basic Rolling Particle algorithm, 3000 iterations, particle life 50. Click to view demo.</span></a></p>
<p>While the algorithm produces inherently center-biased maps, multiplying this across the noise results in islands that are too boxy. To round out the results more, instead of picking a random starting point for particles, let&#8217;s ensure that they land closer to the center:</p>
<p><a href="#demo4" class="thickbox clear" title="Rolling Particle algorithm, center-biased, particles start 12 tiles away from the edges. Click to generate."><img src="/wp-content/uploads/2010/09/dodworldgen-rollingparticle-centerbias.png" title="Rolling Particle algorithm, center-biased, particles start 12 tiles away from the edges. Click to view demo." alt="Rolling Particle algorithm, center-biased, particles start 12 tiles away from the edges. Click to view demo."><span class="caption">Rolling Particle algorithm, center-biased, particles start 12 tiles away from the edges. Click to view demo.</span></a></p>
<p>To absolutely ensure that the islands will not reach the edges, I&#8217;ve also multiplied the outermost tiles by 0.75, and the second outermost tiles by 0.88. These tiles already have some of the lowest values of the map, and softening or &#8220;blurring&#8221; them this way ensures the final map does not touch the edges.<br />
<a name="applying_terrain"></a></p>
<h4>Step 3: Apply Terrain</h4>
<p>Once the base noise map and the rolling particle mask have been generated, multiply the noise values times the (mask/255). Dividing by 255 ensures that the mask values will range from 0 to 1 rather than the normalized 0 to 255. This produces the following result:</p>
<p><a href="#demo5" class="thickbox clear" title="Combined maps. Click to generate."><img src="/wp-content/uploads/2010/09/dodworldgen-final-elevation.png" title="Combined maps. Click to view demo." alt="Combined maps. Click to view demo."><span class="caption">Combined maps. Click to view demo.</span></a></p>
<p>We&#8217;re done with the heightmap generation. Now onto determining the water line and assigning terrain.</p>
<p>I spent some time fussing with linear regression and other estimators to accurately place a water line, but, at the end, directly sampling the values of the map turned out to be the fastest (to program and execute), and most accurate solution. To determine the water line for the default 60% water used in this world generator, step through the map and throw all of the values into an array. Sort this array numerically. The value indexed at (array.length &#8211; 1)*0.6 marks your water line. Everything below it is water, everything above is land.</p>
<p>Now that the waterline is set, I pass that value into each tile&#8217;s <code>setTypeByElevation()</code> function, which sets the tile type according to its elevation, as follows:</p>
<p>If below the water line:</p>
<ul>
<li>If above waterline-40: shallow water.</li>
<li>Else: deep water.</li>
</ul>
<p>If above the water line:</p>
<ul>
<li>If below waterline+15, coast/beach.</li>
<li>If between waterline+15 and waterline+35: plains.</li>
<li>If above 255-25: mountain.</li>
<li>If between 255-50 and 255-25: hills.</li>
<li>Else: forest.</li>
</ul>
<p>Producing this:</p>
<p><a href="#demo6" class="thickbox clear" title="Final result. Click to generate."><img src="/wp-content/uploads/2010/09/dodworldgen-final-terrain.png" title="Final result. Click to view demo." alt="Final result. Click to view demo."><span class="caption">Final result. Click to view demo.</span></a></p>
<p>Grab the source code from <a href="http://code.google.com/p/dance-of-death-worldgen/" target="_blank">Google Code</a>, or <a href="http://dance-of-death-worldgen.googlecode.com/svn/trunk/" target="_blank">directly from SVN</a>. Feel free to tweak any of the values and modify the algorithms as long as you adhere to the <a href="http://www.gnu.org/licenses/gpl.html" target="_blank">GNU General Public License v3</a> and provide attribution and all that. Enjoy!</p>
<p><script>
$('a.thickbox').colorbox({inline:true, innerWidth:704, innerHeight:384, overflow:"hidden"});
</script></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.nolithius.com/articles/world-generation/world-generation-breakdown/feed</wfw:commentRss>
			<slash:comments>15</slash:comments>
		
		
			</item>
		<item>
		<title>Neural Particle Deposition</title>
		<link>http://www.nolithius.com/articles/world-generation/neural-particle-deposition</link>
					<comments>http://www.nolithius.com/articles/world-generation/neural-particle-deposition#comments</comments>
		
		<dc:creator><![CDATA[Ebyan Alvarez-Buylla]]></dc:creator>
		<pubDate>Wed, 16 Mar 2016 07:28:40 +0000</pubDate>
				<category><![CDATA[World Generation]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[art]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[procedural generation]]></category>
		<category><![CDATA[world generation]]></category>
		<guid isPermaLink="false">http://www.nolithius.com/?p=1451</guid>

					<description><![CDATA[In developing an algorithm to generate nodes that are guaranteed to be within a certain distance of each other, I stumbled over this interesting distribution of particles which were initially placed randomly then moved near their nearest neighbor. I&#8217;ve dubbed this particle system &#8220;Neural Particle Deposition&#8221; on account of the organic, neuron-like shapes it produces. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In developing an algorithm to generate nodes that are guaranteed to be within a certain distance of each other, I stumbled over this interesting distribution of particles which were initially placed randomly then moved near their nearest neighbor. I&#8217;ve dubbed this particle system &#8220;Neural Particle Deposition&#8221; on account of the organic, neuron-like shapes it produces. Take a look:<span id="more-1451"></span></p>
<style>
.pip
{
    width: 8px;
    height: 8px;
    background-color: #000000;
    position: absolute;
    border-radius: 4px;
    opacity: 0.4;
}
</style>
<div id="canvas" style="background-color: #e9e8e8; position: relative; width: 580px; height: 580px; margin: 0 auto;"></div>
<p><script type="text/javascript" src="/neural/neural.js"></script></p>
<p>This algorithm is rather straightforward: after picking the starting point, generate one point at a time within the container&#8217;s constraints. If the generated point is too close to its closest point, drop it. Otherwise, move it along the vector to its closest neighbor so it is a certain maximum distance away, then repeat.</p>
<p>The code relies on a container div with the ID of &#8220;canvas&#8221;, which must have an explicit width and height defined, as well as its position attribute set to &#8220;relative&#8221;, so that the pips can be absolutely positioned within it. The placed pips are will be given the class of &#8220;pip&#8221;, with the following initial style:</p>
<pre class="brush: css; title: ; notranslate">
.pip
{
    width: 8px;
    height: 8px;
    background-color: #000000;
    position: absolute;
    border-radius: 4px;
    opacity: 0.4;
}
</pre>
<p>The JavaScript code is as follows:</p>
<pre class="brush: jscript; title: ; notranslate">
$(function()
{
    var newPipInterval = 8;

    // The farthest
    var maxPipRadius = 6;
    var minPipRadius = maxPipRadius * 0.5;
    var avgPipRadius = maxPipRadius * 0.75;
    var pipCount = 600;

    var center;

    var canvas = $(&quot;#canvas&quot;);
    var width = canvas.width();
    var height = canvas.height();

    var pips = new Array();

    reset();

    setInterval(addNewPip, newPipInterval);

    function reset ()
    {
        canvas.empty();
        pips = new Array();
        center = createRandomPip();
        addPip(center);
    }

    function addNewPip ()
    {
        if (pips.length &lt; pipCount)
        {
            addPip(createPip());
        }
        else
        {
            reset();
        }
    }

    function createPip ()
    {
        var randomPip = createRandomPip();
        var nearestPip = getNearestPip(randomPip);
        var pipDistance = distance(randomPip, nearestPip);

        // Too close, toss
        while (pipDistance &lt; minPipRadius)
        {
            randomPip = createRandomPip();
            nearestPip = getNearestPip(randomPip);
            pipDistance = distance(randomPip, nearestPip);
        }

        // Adjust if we're too far
        if (pipDistance &gt; maxPipRadius)
        {
            // Calculate unit vector
            var unitX = (randomPip.x - nearestPip.x) / pipDistance;
            var unitY = (randomPip.y - nearestPip.y) / pipDistance;

            randomPip.x = avgPipRadius * unitX + nearestPip.x;
            randomPip.y = avgPipRadius * unitY + nearestPip.y;
        }

        return randomPip;
    }

    function getNearestPip (pip)
    {
        var nearestPip = center;
        var nearestDistance = distance(pip, center);

        for (var i = 0; i &lt; pips.length; i++)
        {
            var candidatePip = pips[i];
            var candidateDistance = distance(pip, candidatePip);

            if (candidateDistance &lt; nearestDistance)
            {
                nearestPip = candidatePip;
                nearestDistance = candidateDistance;
            }
        }

        return nearestPip;
    }

    function createRandomPip ()
    {
        return {x: rand(0, width), y: rand(0, height)};
    }

    function addPip (pip)
    {
        pips.push(pip);

        var div = document.createElement(&quot;div&quot;);
        div.setAttribute(&quot;class&quot;, &quot;pip&quot;);
        div.style.left = pip.x + &quot;px&quot;;
        div.style.top = pip.y + &quot;px&quot;;

        canvas.append(div);

        $(div).animate({width: &quot;2px&quot;, height: &quot;2px&quot;, opacity: 1}, 500);
    }

    function rand(min, max)
    {
        return Math.floor(Math.random()*(max-min+1)+min);
    }

    function clamp (number, min, max)
    {
        return Math.min(Math.max(number, min), max);
    }

    function distance(pip1, pip2)
    {
        var xs = 0;
        var ys = 0;

        xs = pip2.x - pip1.x;
        xs = xs * xs;

        ys = pip2.y - pip1.y;
        ys = ys * ys;

        return Math.sqrt(xs + ys);
    }
});
</pre>
<p>You can tame the distribution somewhat by altering the container&#8217;s dimensions, as you can see in the header image. To generate a more reliable mountain-range-like distribution, try starting with a narrow container and setting the starting position to one of the ends.</p>
<p>The full source code is available on <a href="https://github.com/Nolithius/neural-particle" target="_blank">GitHub</a> as well as <a href="http://code.google.com/p/neural-particle/" target="_blank">Google Code</a>. Enjoy!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.nolithius.com/articles/world-generation/neural-particle-deposition/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>World Generation Teaser</title>
		<link>http://www.nolithius.com/articles/world-generation/world-generation-teaser</link>
					<comments>http://www.nolithius.com/articles/world-generation/world-generation-teaser#comments</comments>
		
		<dc:creator><![CDATA[Ebyan Alvarez-Buylla]]></dc:creator>
		<pubDate>Tue, 15 Mar 2016 17:05:09 +0000</pubDate>
				<category><![CDATA[World Generation]]></category>
		<category><![CDATA[cocos2d]]></category>
		<category><![CDATA[objective c]]></category>
		<category><![CDATA[procedural generation]]></category>
		<category><![CDATA[progress update]]></category>
		<category><![CDATA[wilderness generation]]></category>
		<category><![CDATA[world generation]]></category>
		<guid isPermaLink="false">http://www.nolithius.com/?p=1357</guid>

					<description><![CDATA[Happy 2013 everyone! Rather than risking going three months without an update, I figured I&#8217;d post some teaser screenshots of the world generation progress on my latest project: Elevation and water line Here&#8217;s the first pass, mostly focused on getting the land formation looking good with Perlin noise, and sampling the water to ensure a [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Happy 2013 everyone! Rather than risking going three months without an update, I figured I&#8217;d post some teaser screenshots of the world generation progress on my latest project:<span id="more-1357"></span></p>
<h4 style="margin-bottom: 0;">Elevation and water line</h4>
<p><a class="thickbox" href="/wp-content/uploads/2013/03/elevation.png" title="Elevation and water line"><img src="/wp-content/uploads/2013/03/elevation-1024x813.png" style="width: 580px;"/></a><br />
Here&#8217;s the first pass, mostly focused on getting the land formation looking good with Perlin noise, and sampling the water to ensure a landmass percentage. I&#8217;ve also ensured the edges of the map taper off by multiplying the elevation values times a box gradient.</p>
<h4 style="margin-bottom: 0;">Perlin distortion</h4>
<p><a class="thickbox" href="/wp-content/uploads/2013/03/elevation_distortion.png" title="Perlin distortion"><img src="/wp-content/uploads/2013/03/elevation_distortion.png" style="width: 580px;"/></a><br />
A plain Perlin noise elevation is pretty tame, so I figured I&#8217;d throw a twist in it this time around and applied a Perlin noise distortion. My distortion implementation involves generating two additional 2D Perlin noise maps, using one to determine the x-offset and another the y. I then sample the original map with these offsets multiplied by a maximum amplitude. It&#8217;s worth noting that Ken Perlin&#8217;s original C implementation outputs values between -1 and 1, so sampling offsets for a distortion is straightforward. It&#8217;s also worth noting that because Objective-C is a superset of C, said original implementation can be used straight out, no porting necessary (although you&#8217;ll need to do some work to output the <a href="http://en.wikipedia.org/wiki/Fractional_Brownian_motion" target="_blank">fBm</a> you&#8217;re likely expecting).</p>
<h4 style="margin-bottom: 0;">Floodfilling to identify landmasses</h4>
<p><a class="thickbox" href="/wp-content/uploads/2013/03/landmasses.png" title="Floodfilling to identify landmasses"><img src="/wp-content/uploads/2013/03/landmasses-1024x813.png" style="width: 580px;"/></a><br />
Landmasses have been floodfilled to identify continents and islands (differences not pictured). I&#8217;ve picked a somewhat arbitrary minimum area to qualify as a continent (I believe around 4000 tiles), which will determine starting areas for players.</p>
<h4 style="margin-bottom: 0;">Wind map</h4>
<p><a class="thickbox" href="/wp-content/uploads/2013/03/wind.png" title="Wind map"><img src="/wp-content/uploads/2013/03/wind-1024x813.png" style="width: 580px;"></a><br />
Inspired by the [now defunct?] <a href="http://www.dungeonleague.com/2010/03/28/wind-direction/" target="_blank">Dungeon League article on Wind Direction</a>, I&#8217;ve generated an interpolated wind map, then distorted the result with a Perlin noise distortion. Pictured are the degrees of the wind mapped to 0-255.</p>
<h4 style="margin-bottom: 0;">Wind vectors over land</h4>
<p><a class="thickbox" href="/wp-content/uploads/2013/03/wind_vectors.png" title="Wind vectors over land"><img src="/wp-content/uploads/2013/03/wind_vectors-1024x813.png" style="width: 580px;"/></a><br />
Arbitrary wind directions are a good starting point, but the purpose of the wind is to determine humidity distribution by simulating how far moisture would have to travel from water to a given tile, with the added obstructions of mountains that are higher than cloud elevation. To this end, the wind direction on one tile must point towards another tile, so it is necessary to clamp the wind directions to the four cardinal and diagonal directions, resulting in 45&deg; zones. The first pass at clamping had hard boundaries between the zones, which meant the resulting rain shadow had too many straight edges, which then resulted in rather unorganically-bound biomes. To solve this, I set up a random dithering rather than clamping. Pictured are wind directions N, NE, E, SE, S, etc. with a corresponding solid color assigned.</p>
<h4 style="margin-bottom: 0;">Rain shadow</h4>
<p><a class="thickbox" href="/wp-content/uploads/2013/03/rain_shadow.png" title="Rain shadow"><img src="/wp-content/uploads/2013/03/rain_shadow-1024x813.png" style="width: 580px;"/></a><br />
Also taking a cue from <a href="http://www.dungeonleague.com/2010/05/22/fast-rain-shadow/" target="_blank">the Dungeon League article on this topic</a>, I then step backwards through the wind vectors, starting at each land tile, and count how many tiles it takes to get to water or to another tile whose humidity has already been set. I set an upper clamp for how long this can go on, in the odd but remotely possible case that you catch a wind loop that never touches water. This max value is also assigned to areas above cloud elevation, which results in mountains creating a rain shadow.</p>
<h4>Next steps</h4>
<p>I&#8217;ve stopped just short of identifying biomes, which is the next step, precluded by a quick temperature gradient generation.</p>
<p>For this particular game, biomes add flavor rather than being a key part of the gameplay, so I&#8217;ve shifted gears to building a simple tiling system to represent the terrain. After all, each world tile will be larger than two pixels in the actual game!</p>
<p><script>
$('a.thickbox').colorbox();
</script></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.nolithius.com/articles/world-generation/world-generation-teaser/feed</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title>WeightedLetter Name Generator</title>
		<link>http://www.nolithius.com/articles/procedural-generation/weightedletter-name-generator</link>
					<comments>http://www.nolithius.com/articles/procedural-generation/weightedletter-name-generator#comments</comments>
		
		<dc:creator><![CDATA[Ebyan Alvarez-Buylla]]></dc:creator>
		<pubDate>Sun, 13 Mar 2016 20:40:28 +0000</pubDate>
				<category><![CDATA[Procedural Generation]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[name generation]]></category>
		<category><![CDATA[procedural generation]]></category>
		<category><![CDATA[source code]]></category>
		<guid isPermaLink="false">http://www.nolithius.com/?p=1079</guid>

					<description><![CDATA[This name generator takes a seed of similar sounding names (or any words), and generates a new set of names based on the likelihood that one letter follows another in the original set. It picks the first and last letter, generates the letters in between, best-matches the second-to-last letter, and runs post-generation triple-letter and Damerau&#8211;Levenshtein [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>This name generator takes a seed of similar sounding names (or any words), and generates a new set of names based on the likelihood that one letter follows another in the original set. It picks the first and last letter, generates the letters in between, best-matches the second-to-last letter, and runs post-generation triple-letter and Damerau&ndash;Levenshtein checks to ensure uniformity with the seed.<span id="more-1079"></span></p>
<p>Originally named the DamerauLevenshteinNamegen, in honor of its last filter step, this generator was first written in PHP, ported to AS3 for use in <em><a href="http://www.nolithius.com/dod">Dance of Death</a></em>, and now to Objective C for <em><a href="https://itunes.apple.com/us/app/crossword-dungeon/id560785195?ls=1&#038;mt=8" target="_blank">Crossword Dungeon</a></em>. The source code is available on <a href="https://github.com/Nolithius/weighted-letter-namegen" target="_blank">GitHub</a> as well as <a href="http://code.google.com/p/weighted-letter-namegen/" target="_blank">Google Code</a>.</p>
<p>Let&#8217;s break it down, step-by-step:</p>
<h4>Step 1: Parse the Letter Distribution</h4>
<p>This is the largest part and core of this generator: we step through each name in the seed, then through each letter in that name, and keep track of how likely that letter is to follow its prior letter. We also keep track of the sizes of the names, to ensure the generated names are consistently sized. We only need to do this parsing once (or any time the seed changes). </p>
<p>After we&#8217;ve got the letter distribution recorded, it&#8217;s time to generate some names. We begin by picking a size and a starting letter, then pick following letters based on how likely they are to follow the previous letter in the seed names, until we&#8217;ve reached the length of the selected size (let&#8217;s call this process the <em>name body generation loop</em>). This is what we end up with (click <strong>Generate</strong> to generate a new batch of names, or click on the list of seed names to edit them):</p>
<p><embed src="/wp-content/uploads/2013/05/namegen_firstpass.swf" allowfullscreen="false" allowscriptaccess="always" style="width: 580px; height: 320px;"></p>
<h4>Step 2: The Beginning and the End</h4>
<p>The generated names are acceptable, but a bit weak, largely because there is no post-processing done to them, but mostly because the first and last letter do not follow the seed distribution. Even though <a href="http://scienceavenger.blogspot.com/2007/12/cambridge-word-scramble-study-its-fake.html" target="_blank">the &#8220;Cambridge study&#8221; was bogus</a>, there is still an intrinsic importance to the way a word starts and ends. To improve the algorithm, let&#8217;s keep track of the likelihood that a letter appears first and the likelihood that it appears last.</p>
<p>Picking the first letter is straightforward: we track it in a weighted array and pick from that; picking the last one is not so trivial. We can pick the last letter before the name body generation loop then best-fit the penultimate letter at the end of the loop (this is the solution I went with), or we can pick the last letter within the name body generation loop by prioritizing letters with higher &#8220;lastLetter&#8221; weight when picking the last letter (you are welcome to experiment with this approach!).</p>
<p>Thus we achieve:</p>
<p><embed src="/wp-content/uploads/2013/05/namegen_beginning_and_end.swf" allowfullscreen="false" allowscriptaccess="always" style="width: 580px; height: 320px;"></p>
<h4>Step 3: Postprocessing</h4>
<p>This is an entirely optional step, since the generator at this point is pretty solid. For some additional refinement, however, we can look to two post-process filters: triple-letter checks, and maximum <a href="http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance" target="_blank">Damerau&ndash;Levenshtein distance</a> from seed names.</p>
<p>The triple letter check is straightforward: step through the word, and ensure no three characters in a row are the same. This is a surprisingly likely occurrence if you have names in your seed with same-letter pairs, since a letter is allowed to follow itself and can do so recursively. In this implementation, this check is being done as a postprocess step, but it can also be integrated into the name body generation loop.</p>
<p>The Damerau&ndash;Levenshtein check ensures that the generated word is close enough to at least one of the names in the seed by measuring the Damerau&ndash;Levenshtein distance of the generated name to all of the names in the seed until it finds one whose distance is below the threshold (half of the name length works well). What this means is that we want to keep the general structure of half of the generated name, with some room for letter additions, subtractions, replacements, and swaps. This check ends up filtering out names that are very off-the-wall, which you might very well want to keep; it can also be somewhat costly if you have a large number of seed names. I&#8217;ve skipped it in the Objective C version without any regrets!</p>
<p>Here is the final algorithm at work:</p>
<p><embed src="/wp-content/uploads/2013/05/namegen_postprocessing.swf" allowfullscreen="false" allowscriptaccess="always" style="width: 580px; height: 320px;"></p>
<p>Grab the source code from <a href="https://github.com/Nolithius/weighted-letter-namegen" target="_blank">GitHub</a> and <a href="http://code.google.com/p/weighted-letter-namegen/" target="_blank">Google Code</a>. Feel free to tweak any of the values and modify the algorithm; attribution&#8217;s always appreciated, but <a href="http://www.nolithius.com/game-development/world-generation-breakdown">last time</a> I released code under GPLv3 it was met with some discontent, so have fun with it and let me know in what ways you improve the system!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.nolithius.com/articles/procedural-generation/weightedletter-name-generator/feed</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Guildmaster Alpha Progress</title>
		<link>http://www.nolithius.com/updates/guildmaster/guildmaster-alpha-progress</link>
					<comments>http://www.nolithius.com/updates/guildmaster/guildmaster-alpha-progress#comments</comments>
		
		<dc:creator><![CDATA[Ebyan Alvarez-Buylla]]></dc:creator>
		<pubDate>Wed, 03 Feb 2016 04:27:41 +0000</pubDate>
				<category><![CDATA[Guildmaster]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[guildmaster]]></category>
		<category><![CDATA[management games]]></category>
		<category><![CDATA[pc games]]></category>
		<category><![CDATA[progress update]]></category>
		<category><![CDATA[starling]]></category>
		<category><![CDATA[strategy games]]></category>
		<guid isPermaLink="false">http://www.nolithius.com/?p=2006</guid>

					<description><![CDATA[Guildmaster has progressed rather nicely in the months since the last update, so it is worth taking some time to collate some screenshots showcasing such progress. Most of these were initially posted on Twitter, currently the best avenue to receive bleeding-edge updates on the project. Let&#8217;s dive in: The Party Inventory UI Taking an experience-first [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="http://www.nolithius.com/guildmaster"><em>Guildmaster</em></a> has progressed rather nicely in the months since the last update, so it is worth taking some time to collate some screenshots showcasing such progress. Most of these were initially posted on <a href="http://www.twitter.com/nolithius" target="_blank">Twitter</a>, currently the best avenue to receive bleeding-edge updates on the project. Let&#8217;s dive in:<span id="more-2006"></span></p>
<h4>The Party Inventory UI</h4>
<p>Taking an experience-first approach, I&#8217;ve focused the last chunk of work on the party inventory UI, the primary interface to equip heroes and view party composition at a glance.</p>
<p>This first pass is mostly visual. At the time this screenshot was taken, the equipment system was in place as well as the primary stats directly affecting a character&#8217;s expendable attributes (supplies, mana, energy, and health):</p>
<p><a class="thickbox" href="/wp-content/uploads/2016/02/inventory2.png" title="Inventory is starting to shape up" rel="gallery"><img src="/wp-content/uploads/2016/02/inventory2.png" width="580" /></a></p>
<p>It took a bit of layout rejiggering to fit the remaining areas of relevant information. In this next pass, XP, defenses, to-hit, and a hero&#8217;s gold crowd the scene a bit, though luckily not much more information was missing:</p>
<p><a class="thickbox" href="/wp-content/uploads/2016/02/stats.png" title="Hymn" rel="gallery"><img src="/wp-content/uploads/2016/02/stats.png" width="580" /></a></p>
<p>I then took a brief detour from top-level, high priority implementation to focus on something that&#8217;s high on everyone&#8217;s coolness list: dual wielding. It was a good thing I tackled this seemingly frivolous feature this early on, because it required a rethinking of the underlying attack system that resulted in a more robust, extensible system that will allow weapon skills to add special attacks, and magic skills to add battle spells to a character&#8217;s arsenal. Here&#8217;s a dashing rogue brandishing dual swords:</p>
<p><a class="thickbox" href="/wp-content/uploads/2016/02/Dualwield.png" title="Hymn" rel="gallery"><img src="/wp-content/uploads/2016/02/Dualwield.png" style="margin: 0 auto; display: block;" /></a></p>
<p>This last UI screenshot reflects the latest and greatest. While visually not much different from the previous one, other than the morale meter, the characters&#8217; special traits are now implemented. Featured in this screen: <strong>Curmudgeon</strong>, which reduces morale gain by 50% and increases morale loss by 50% for the entire party; <strong>Thief</strong>, which causes the hero to pocket a percentage of the loot after completing an attack; <strong>Shortsight</strong>, which reduces the sight range for the party if all members are shortsighted; and <strong>Point Blank Shot</strong>, which allows a hero without a melee weapon equipped to use a ranged weapon in a front rank:</p>
<p><a class="thickbox" href="/wp-content/uploads/2016/02/full_inventory.png" title="Hymn" rel="gallery"><img src="/wp-content/uploads/2016/02/full_inventory.png" width="580" /></a></p>
<h4>Guildmaster Website</h4>
<p>Also a slight detour from the to-do list, the bug to put together a quick layout for the <em>Guildmaster</em> site bit me; so I mocked it up and begun slicing it and building it out:</p>
<p><a class="thickbox" href="/wp-content/uploads/2016/02/website.png" title="Guildmaster website in the works" rel="gallery"><img src="/wp-content/uploads/2016/02/website.png" width="580" /></a></p>
<p>That gets us current! I&#8217;ll be releasing out Alpha 2 to my internal testers for some early feedback and review shortly, then will move on to the next major areas of missing functionality: XP gaining, leveling up, and city development.</p>
<p><script>
$('a.thickbox').colorbox();
</script></p>
]]></content:encoded>
					
					<wfw:commentRss>http://www.nolithius.com/updates/guildmaster/guildmaster-alpha-progress/feed</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
