tag:blogger.com,1999:blog-17908627546507704522024-02-19T11:07:42.192+01:00The Shee's lost knowledgeUncovering the Creatures game series technical secrets together.The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.comBlogger32125tag:blogger.com,1999:blog-1790862754650770452.post-16762211382616351282015-06-06T19:15:00.000+02:002015-06-15T10:48:01.679+02:00Making a C1 and C2 Tricorder (knowing exactly what any cob does at a glance)Creatures 2 could easily have become my favorite game in the series.<br />
But as has already been<a href="http://discoveralbia.com/2015/04/the-many-troubles-with-creatures-2.html"> pretty well explained</a>, it was way to frustrating on many levels.<br />
<br />
One of the major reasons I never really got into the game was the overwhelming quantity of new game items, plants and foods .<br />
No guide existed at the time to explain their effects, and even today the few that exist lack in <span style="font-family: inherit;">completeness </span>or precision.And without any reference it was a very frustrating experience not to know what could or could not be eaten.I'll admit it, many of my C2 Norns never ate anything beyond cheese carrots or nuts by fear of the unknown.<br />
<br />
Writing such a guide might be an option, but what about the various additional cobs one might not be aware of , or all future additions?<br />
Can we be a little more clever about that?<br />
What if we got a tool that simply told us what a cob does by hovering the mouse over it ?<br />
That would be a creatures Tricorder of sorts, that we will learn to build together in this article.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9qiOsgQ7RP-GlrdgRyU8gff5KXT7l0q-QirPphuWx-ZEmEICSmL-tvHx_NdLIiTax-Moy7xkzMTJpjpwnj9SHNP1Cmb4dYo8Eo7YX5J302S8zfvO0wfLxmZqYwG_OSyEHSAnNLLYzTOXz/s1600/tri.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9qiOsgQ7RP-GlrdgRyU8gff5KXT7l0q-QirPphuWx-ZEmEICSmL-tvHx_NdLIiTax-Moy7xkzMTJpjpwnj9SHNP1Cmb4dYo8Eo7YX5J302S8zfvO0wfLxmZqYwG_OSyEHSAnNLLYzTOXz/s1600/tri.PNG" /></a></div>
<br />
<br />
<br />
<a name='more'></a><br />
Some of you may feel that many of the articles I published so far were pretty technical and maybe not that interesting for the common player.<br />
I agree with you.<br />
<br />
The reasoning behind that is that I'm trying to share knowledge about the various game mechanics so anybody can make their own tools suited to whatever needs might arise.<br />
There is a lot of things to cover, and I realize I spent a lot of time on the baby steps and didn't even show you most of the "good stuff" yet.<br />
<br />
Let's try to correct this and make a tool that can automatically show you the effects of any cob you point your mouse at.<br />
This is the single most important tool I really would have liked to get with the Creatures 2 game, and one of the reasons I spent so much time on technical details so far.<br />
<br />
<h4>
Putting stuff together</h4>
So what do we need to build such a tool ?<br />
<br />
As <a href="http://sheeslostknowledge.blogspot.fr/2015/05/finding-out-what-is-what-in-creatures-1.html">I've shown recently</a>, it's pretty easy to make a tool that spits out the classifier for any object you hover your mouse over.<br />
<br />
Let's build on top of that.<br />
<br />
We've got a way to get the classifier for the object under the cursor.<br />
As shown in the <a href="http://sheeslostknowledge.blogspot.fr/2015/05/a-smart-ish-c1-scriptorium-browser.html">C1 scriptorium article</a>, this enables us to recover any script for this object family by using the " dde: scrp X Y Z N" command , where X Y and Z are the classifier, and N an "event number".<br />
<br />
The events we would be interested in are the" activate 1" and 2 actions (script number 0 and 1) for C1.<br />
In C2, we also have the number 12 script that corresponds to the eating action.<br />
(Remember that in C1 creatures "activate" food as any other item, while in C2 there are distinct actions for activation and eating)<br />
<br />
Modifying the tool to spit out the activation or eating script instead of the classifier is then trivial, but let's do more.<br />
<br />
As <a href="http://discoveralbia.com/2015/05/a-c1-caos-lesson-for-everyone.html">Jessica recently showed by documenting the C1 carrot cob inner workings</a>, the main CAOS command behind the "effects" of any cob is the "stim writ" command. <br />
<br />
This command not only injects the Norn with the needed chemicals, but also "fires" it's associated brain cells so the creature can trigger the learning process for this object (and later remember that eating food when hungry is a good thing, or that eating a bad plant is not a good idea).<br />
<br />
Let's take the "stim writ" command used by the Activate1 script for carrots :<br />
<span style="color: lime;"><br /></span>
<span style="color: #fce5cd;"><span style="font-family: "Courier New",Courier,monospace;">stim writ from 10 255 0 0 35 100 34 70 57 100 0 0 </span></span><br />
<br />
The structure of this command is identical for C1 and C2, and the numbers are interpreted as such:<br />
<br />
<span style="color: #fce5cd;"><span style="font-family: "Courier New",Courier,monospace;">stim writ <span style="color: lime;"># The command itself</span></span></span><br />
<span style="color: #fce5cd;"><span style="font-family: "Courier New",Courier,monospace;">from <span style="color: lime;"># The object to which the stimulus must be applied."from" is the entity that lead to the script being executed.</span></span></span><br />
<span style="color: #fce5cd;"><span style="font-family: "Courier New",Courier,monospace;">10 <span style="color: lime;">#Significance of the event.This tunes the impact of this action on the Norn's learning process.</span></span></span><br />
<span style="color: #fce5cd;"><span style="font-family: "Courier New",Courier,monospace;">255 <span style="color: lime;"># Sensory lobe Neuron Number: defines if this stimulus should fire a specific neuron</span></span></span><br />
<span style="color: #fce5cd;"><span style="font-family: "Courier New",Courier,monospace;">0 <span style="color: lime;"># Intensity: the amount by which the corresponding Neuron will be activated</span></span></span><br />
<span style="color: #fce5cd;"><span style="font-family: "Courier New",Courier,monospace;">0 <span style="color: lime;"># Features: I'm not sure what this field does yet.</span></span></span><br />
<span style="color: #fce5cd;"><span style="font-family: "Courier New",Courier,monospace;">35 100 <span style="color: lime;"># Chemical1 number to inject to the target, and it's amount</span></span></span><br />
<span style="color: #fce5cd;"><span style="font-family: "Courier New",Courier,monospace;">34 70 </span><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">#Chemical2 number to inject to the target, and it's amount</span></span></span><br />
<span style="color: #fce5cd;"><span style="font-family: "Courier New",Courier,monospace;">57 100 </span><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">#Chemica3 number to inject to the target, and it's amount</span></span></span><br />
<span style="color: #fce5cd;"><span style="font-family: "Courier New",Courier,monospace;">0 0 </span><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">#Chemical4 number to inject to the target, and it's amount</span></span></span><br />
<br />
We can safely discard the 6 first elements unless we're studying the brain specifically.<br />
<br />
Making sense of which chemical is which is easy, as I've shown in the <a href="http://sheeslostknowledge.blogspot.fr/2014/01/the-creatures-1-chemicalstxt-file-format.html">C1 </a>and <a href="http://sheeslostknowledge.blogspot.fr/2014/01/getting-c2-chemicals-descriptions.html">C2 </a>chemicals definitions acquiring articles.<br />
<br />
Don't forget that C2 also has a couple "stm#" commands.<br />
Those don't have a specific target, but rather are sent to all nearby norns depending on the used variation : All nearby Norns, all touching Norns, all Norns within hearing range...<br />
This is useful to generate "zone" effects such as those of music or contamination. <br />
<br />
Now we've got everything we need to make a simple yet very powerful tool:<br />
<br />
- Grab the Classifier for the object under the cursor<br />
- Get the Activate or Eat script for this classifier<br />
- Only keep the "stim writ" line <br />
- Split that line into 4 chemical injection entries, and figure out which chemical is which by referring to the chemicals list obtained by parsing the game files.<br />
<br />
We now can now know <span id="goog_1370778701"></span><span id="goog_1370778702"></span>what a given object does by just pointing our mouse at it!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkxmQD5adbQvUtexlWFhi_hBXMa0rbEOMO3VLDzIbVYxzGiTP9IjnBmd6hNdXu_t9ui45X_KvEJ7nCm5D4VYs0JtshasqF8hX0f6L3EUU1_-3vp_x5lgEya-0L9Rz5PR7CShv-Fy4ca9st/s1600/good.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkxmQD5adbQvUtexlWFhi_hBXMa0rbEOMO3VLDzIbVYxzGiTP9IjnBmd6hNdXu_t9ui45X_KvEJ7nCm5D4VYs0JtshasqF8hX0f6L3EUU1_-3vp_x5lgEya-0L9Rz5PR7CShv-Fy4ca9st/s1600/good.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">So this herb is the good one...</td><td class="tr-caption" style="text-align: center;"><br /></td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_zhb_q4fC4hWgLbtrKrzT_Y5omDyssqp4-KwOYxkVUuq1r0iAuUB4nIU6JPO6pkeZLo3R6-KRr1jVW-_YnR5uclzT0hRCcHm3LD0ky95UlOPS_hAMrLbsSRbnAf32eqaIwMJpUvKR8JHK/s1600/bad.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_zhb_q4fC4hWgLbtrKrzT_Y5omDyssqp4-KwOYxkVUuq1r0iAuUB4nIU6JPO6pkeZLo3R6-KRr1jVW-_YnR5uclzT0hRCcHm3LD0ky95UlOPS_hAMrLbsSRbnAf32eqaIwMJpUvKR8JHK/s1600/bad.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">... and this is one is the bad.</td></tr>
</tbody></table>
<br />
<h3>
Exploring some stuff</h3>
<br />
Now we've finally got such a tool, we can quickly go over a couple of the most ambiguous items in the C2 world, for science:<br />
<br />
<br />
First, let's answer a question I raised in my very first post as I started this blog, and figure out which side of the bridge is the safe one :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix_Vt_kIxLZN0axXgf8tfnDlZLldeGUJgM53GWQ2x4VM31FaVf69NHs9ZlWwSZ-L0goM7bpVgmECEOky_3N769qhstxhkQtDC4cEiTv2vqldEnzGrya7HWX8Lt7kCB-jhqcTSANhjJliwZ/s1600/good1.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix_Vt_kIxLZN0axXgf8tfnDlZLldeGUJgM53GWQ2x4VM31FaVf69NHs9ZlWwSZ-L0goM7bpVgmECEOky_3N769qhstxhkQtDC4cEiTv2vqldEnzGrya7HWX8Lt7kCB-jhqcTSANhjJliwZ/s1600/good1.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The left side berries are the safe ones, and have healing properties</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuNI_FA1gsqxLnNp9hvfPNf4rx3abd47H69zL2I9i3s7eTYgIwTwxuXojM0-2N_fLy5OcpOReVxJH1EEAvPNf_UpNMOGQEzJn2dT7jwV5u82my9GQ9FjDzyfCuLroOa9dp-UohxYBRSAKf/s1600/bad1.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuNI_FA1gsqxLnNp9hvfPNf4rx3abd47H69zL2I9i3s7eTYgIwTwxuXojM0-2N_fLy5OcpOReVxJH1EEAvPNf_UpNMOGQEzJn2dT7jwV5u82my9GQ9FjDzyfCuLroOa9dp-UohxYBRSAKf/s1600/bad1.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">While the right side of the bridge bears the toxic variety.</td></tr>
</tbody></table>
<br />
And while we're at it, let's have a look at more lookalikes.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioUymskG_9Z5gHYMDdT8viOerwf6kyfuNEimi656UePd5cpt1SzI0l3uD6xqhWnQhOF3hvNufaVNF30h2QGpgDYOm14C-zhVSPnZKZULWunb0hOgj13GzZQL0ccJahWMeJ7moULe6qUDvd/s1600/good2.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioUymskG_9Z5gHYMDdT8viOerwf6kyfuNEimi656UePd5cpt1SzI0l3uD6xqhWnQhOF3hvNufaVNF30h2QGpgDYOm14C-zhVSPnZKZULWunb0hOgj13GzZQL0ccJahWMeJ7moULe6qUDvd/s1600/good2.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The blue berries are tasty,refreshing, and cure cyanide poisoning...</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjcG3a3LjehX6FH_mEPhZFP1oL1exiKuLaP7J7gkHvOe82Dols-8xiNsNPOhRpwgNxGAwWLij6RKsY6dpoV5cSGjhXznxO3DWzqCw2wexSUs_Ib20oorJzXhF4N3Pu0uIGRfiigvTfaFxb/s1600/bad2.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjcG3a3LjehX6FH_mEPhZFP1oL1exiKuLaP7J7gkHvOe82Dols-8xiNsNPOhRpwgNxGAwWLij6RKsY6dpoV5cSGjhXznxO3DWzqCw2wexSUs_Ib20oorJzXhF4N3Pu0uIGRfiigvTfaFxb/s1600/bad2.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">... and should probably not be confused with the red ones from the same bush.</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi02OLRRxbcq6O2FFclMWS0cIhXm8YlGuvR7pCPXbc00xL2jS0-EhLvm0P9oAT-HBf5iypFa2zYDp1vhHSLNNZ1do5nP76yTanqtIsn7_yb_fvX8Q4lsfZJTN9Pd6qHSv2pJ59aEpBP7oXj/s1600/goodchamp.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi02OLRRxbcq6O2FFclMWS0cIhXm8YlGuvR7pCPXbc00xL2jS0-EhLvm0P9oAT-HBf5iypFa2zYDp1vhHSLNNZ1do5nP76yTanqtIsn7_yb_fvX8Q4lsfZJTN9Pd6qHSv2pJ59aEpBP7oXj/s1600/goodchamp.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Small shrooms are mostly ok.</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL6UvG1-kNwzzOmqmv-LV91EEGqw03aJbYKwSKlXvHCGyiQuAITuDJ2YhwmFjunwyhtsxTeD08OF87KAkIRKznBZgYwLY3pGBgIAoYmSHjrLMt9BxpmpEuyx5cQLi74LdazEGapCdQ6pbf/s1600/badchamp.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL6UvG1-kNwzzOmqmv-LV91EEGqw03aJbYKwSKlXvHCGyiQuAITuDJ2YhwmFjunwyhtsxTeD08OF87KAkIRKznBZgYwLY3pGBgIAoYmSHjrLMt9BxpmpEuyx5cQLi74LdazEGapCdQ6pbf/s1600/badchamp.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">And I guess you already knew about the big ones</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIcn5iqm1U52yVRmi7Os2Iq5NmkA5UH9uVG6JLB_CtK1xukreGY0lH69F-HFs91YApm4UCJk28Hbl2EELNL9dUQp7S542AlWNTCJrHcbpN4Wd6N71Yb3OMznTPcsnD4fv4tQiRf1yjRMfV/s1600/cactus.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIcn5iqm1U52yVRmi7Os2Iq5NmkA5UH9uVG6JLB_CtK1xukreGY0lH69F-HFs91YApm4UCJk28Hbl2EELNL9dUQp7S542AlWNTCJrHcbpN4Wd6N71Yb3OMznTPcsnD4fv4tQiRf1yjRMfV/s1600/cactus.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Those not only hurt but are also toxic ! Now I know how my norns get ill so close to the nursery!</td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-JYkYAeCfUTXJQN4bGK9PZPDLRx__iTSx_y9WtsB2DrnSxNICRP9lwHtdgcGKtZSzSWT-zL7UBy1fdQilHLojKXqyMSNwsXkW2ZaA1gebVW-C9DDNLpSQX2tOFO0RmFji1uKVcRF5XGb5/s1600/ball.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-JYkYAeCfUTXJQN4bGK9PZPDLRx__iTSx_y9WtsB2DrnSxNICRP9lwHtdgcGKtZSzSWT-zL7UBy1fdQilHLojKXqyMSNwsXkW2ZaA1gebVW-C9DDNLpSQX2tOFO0RmFji1uKVcRF5XGb5/s1600/ball.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">And it works on objects too :)</td></tr>
</tbody></table>
<br />
And as always, exploring Albia might lead to a couple interesting surprises:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img alt="" src="data:image/png;base64,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" style="margin-left: auto; margin-right: auto;" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">C1 Norns seem to be claustrophobic </td></tr>
</tbody></table>
<div style="text-align: center;">
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDoMHVbNQtDeNCiWcCRxC207JTXjmpzz-wpQ_SXrYUipNmsh2tRZvj-Nt7Fr74NBk18q17iko7Z9dUXRUbHWDFsW5kXVIXKbS1Ml7nVyIzQSNWF8_8Fq5rDnL5unI6tZoUZW0vxIGB64qW/s1600/c2lift.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDoMHVbNQtDeNCiWcCRxC207JTXjmpzz-wpQ_SXrYUipNmsh2tRZvj-Nt7Fr74NBk18q17iko7Z9dUXRUbHWDFsW5kXVIXKbS1Ml7nVyIzQSNWF8_8Fq5rDnL5unI6tZoUZW0vxIGB64qW/s1600/c2lift.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">C2 ones are also to some extent.</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<h3>
</h3>
<div style="text-align: center;">
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh77BUl3d3TyLraIoNab-YxvUvkAQ9KOU5PzobPrDaypoMJO4-B2-7gZ4FG5NVC8ORIIqUHC9rYjh1YjhhE8FCUOFXCSoF_ZhK3N2oilJQhap2DgVu0ra8cxzwXSY_QSlpTh8ygd4RXupvX/s1600/pball.PNG"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh77BUl3d3TyLraIoNab-YxvUvkAQ9KOU5PzobPrDaypoMJO4-B2-7gZ4FG5NVC8ORIIqUHC9rYjh1YjhhE8FCUOFXCSoF_ZhK3N2oilJQhap2DgVu0ra8cxzwXSY_QSlpTh8ygd4RXupvX/s1600/pball.PNG" /></a></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
Some objects do what you would expect from them...</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnT6SyoBsBar-kDJFJctPT4OHvbOPMVKc6_cEHFzCZhnOwljWGu7NorxVzKcBrvHgv811GpFvAd3kCIbyLgD4xJYdG9-hzo1CaX51tUBqmH8kSeCe_S6DhZckRO3c2g0h31j7yqwpaosw-/s1600/fire.PNG"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnT6SyoBsBar-kDJFJctPT4OHvbOPMVKc6_cEHFzCZhnOwljWGu7NorxVzKcBrvHgv811GpFvAd3kCIbyLgD4xJYdG9-hzo1CaX51tUBqmH8kSeCe_S6DhZckRO3c2g0h31j7yqwpaosw-/s1600/fire.PNG" /></a></div>
<div style="text-align: center;">
...while other are unexpected source of danger.</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
</div>
<h3 style="text-align: center;">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeQam2YaNJyp7DkpsprC710E-gEq8JOsrlaJ5Tmyw8ePwtXAAV2kP0IvWgHO6AUFw0pjBIucxg2VHuLdtTClp7v4CrFrEnup_ogDBy3v1TcS1bwm_IIVMLAlm76ag6Qp_-ujwMibFbUuCn/s1600/triabgl.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeQam2YaNJyp7DkpsprC710E-gEq8JOsrlaJ5Tmyw8ePwtXAAV2kP0IvWgHO6AUFw0pjBIucxg2VHuLdtTClp7v4CrFrEnup_ogDBy3v1TcS1bwm_IIVMLAlm76ag6Qp_-ujwMibFbUuCn/s1600/triabgl.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Who'd have guessed that music gives courage to Norns too ?</td></tr>
</tbody></table>
</h3>
<h3>
Download</h3>
<span style="font-family: inherit;">I ho<span style="font-family: inherit;">pe that's enough t<span style="font-family: inherit;">o have you interested in that tool.</span></span></span><br />
<span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;">You can<span id="goog_1265909874"></span><a href="https://www.blogger.com/goog_1265909873"> </a></span></span></span></span><a href="https://drive.google.com/file/d/0B9mJUJuZTR2EQ005R053QTB0VFk/view?usp=sharing">grab it here</a>.<span id="goog_1265909875"></span><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"> </span></span></span><br />
<br />
And just like the couple preceding tools, you will need to have the <a href="https://support.microsoft.com/en-us/kb/192461">VB6 runtime library</a> installed for it to work.The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com15tag:blogger.com,1999:blog-1790862754650770452.post-9262742172756993312015-05-28T15:23:00.000+02:002015-05-28T15:24:03.686+02:00Finding out what is what in Creatures 1 & 2One of the most frustrating aspects of trying to understand C1 or C2 cobs might just be the first step you need to take.<br />
<br />
Say you are looking at an object, and wonder "What is this object's classifier so I can look up it's scripts ?"<br />
Or the other way round ? What if you find an interesting script and wonder which object it governs?<br />
<br />
I've found no easy way so far to answer those questions, and got tired pretty quick of trying to manually look up my targets each time.<br />
<br />
Cross referencing the various online lists of classifiers didn't cut it either: many of them are at best incomplete when not downright wrong.And they are limited to the standard game items, with obviously no way to reference every single COB ever made.<br />
<br />
Things don't have to be this way.<br />
Read through this very quick article with me, and grab a tool that makes the job as simple as hovering the hand over an object to get the needed information.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDOUE6VizJBzkYhVpY3ulj0NIpdSNODSMPVB_Ectt7fIMEeBWAlIc6KWVVh5NaYe2Jil4j9COQ2D6GHQSWO4poINEkYaL5-x5oWhONk7-DvSsYZ7RZNuvaaKyYr8itoP6qPUr4zxcgEgFW/s1600/intro.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDOUE6VizJBzkYhVpY3ulj0NIpdSNODSMPVB_Ectt7fIMEeBWAlIc6KWVVh5NaYe2Jil4j9COQ2D6GHQSWO4poINEkYaL5-x5oWhONk7-DvSsYZ7RZNuvaaKyYr8itoP6qPUr4zxcgEgFW/s1600/intro.PNG" /></a></div>
<br />
<br />
<a name='more'></a><br />
<br />
<h3>
Identifying things from a classifier</h3>
As I've already mentioned in <a href="http://sheeslostknowledge.blogspot.fr/2015/05/a-smart-ish-c1-scriptorium-browser.html">previous articles </a>, one <a href="http://sheeslostknowledge.blogspot.fr/2013/12/caos-snippets.html">CAOS command</a> I like to use is a simple command to quickly identify an object by it's classifier is :<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">rtar X Y Z,sys: camt,sys: edit posl post posr posb </span></span><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjb_eDz47UpFSGdMVAVftG9qzbwyAGk_HIS4V8Im0njcu_z8Ii5mQbsIWuC52YmY3mWxtMZ25GhlI1ZspaWtn18zGaH8NetuMvS9cH8oeHUVK61df5XhCsvkr92rLnJOSmr5FRgMyK4H9oj/s1600/showmeone.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjb_eDz47UpFSGdMVAVftG9qzbwyAGk_HIS4V8Im0njcu_z8Ii5mQbsIWuC52YmY3mWxtMZ25GhlI1ZspaWtn18zGaH8NetuMvS9cH8oeHUVK61df5XhCsvkr92rLnJOSmr5FRgMyK4H9oj/s1600/showmeone.PNG" /> </a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<span style="font-family: inherit;"></span><span style="font-family: inherit;"></span><br />
<span style="font-family: inherit;"></span><br />
<span style="font-family: inherit;"></span><br />
<span style="font-family: inherit;">This is useful when you want to know what object a classifier corresponds to, but let's face it, the ability to obtain a given object's classifier by sight would be even more useful.</span><br />
<br />
<h3>
<span style="font-family: inherit;">Identifying a classifier from an object</span></h3>
<span style="font-family: inherit;">C2 offers the "ETCH,NEXT" command to help enumerate through all objects currently touching the owner of the script.</span><br />
<span style="font-family: inherit;">But to make our solution C1 compatible, we will need to only use commands present in both games.</span><br />
<br />
<span style="font-family: inherit;">We will be using the following script to achieve the expected effect:</span><br />
<br />
<span style="font-family: inherit;"><br /><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> enum 0 0 0,<br /> doif touc targ pntr gt 0,<br /> doif targ ne pntr,<br /> sys: edit posl post posr posb,<br /> dde: putv fmly,<br /> dde: putv gnus,<br /> dde: putv spcs,<br /> stop,<br /> endi,<br /> endi,<br />next</span></span></span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">What does it do ?</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> enum 0 0 0, </span></span></span># Iterate through all objects in the world<span style="font-family: inherit;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><br /> doif touc targ pntr gt 0, </span></span></span># Only enter this bloc if current object in loop does touch the mouse pointer<span style="font-family: inherit;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><br /> doif targ ne pntr, </span></span></span># Only enter this bloc if current object IS NOT the pointer itself.Because technically, yes, the pointer does touch itself.<br />
<span style="font-family: inherit;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><br /> sys: edit posl post posr posb, </span></span></span># Draw the edit box using objects edges<br />
<span style="font-family: inherit;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><br /> dde: putv fmly, </span></span></span># Print out objects Family<span style="font-family: inherit;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><br /> dde: putv gnus, </span></span></span># Print out objects Genus<span style="font-family: inherit;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><br /> dde: putv spcs, </span></span></span># Print out objects Specie<span style="font-family: inherit;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><br /> stop, </span></span></span># exit the loop once we found the first object, otherwise we would end up only circling the last object in the list of objects touching the pointer.<span style="font-family: inherit;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><br /> endi,<br /> endi,<br />next</span></span></span><br />
<br />
<br />
This command although slightly sub optimal is compatible with C1 & C2, and allows you to know at a glance the classifier of the object under the cursor.<br />
<br />
Contrary to the preceding command, having to type this script in a CAOS console would make aiming the cursor highly impractical.<br />
One could technically implement a CAOS only solution, but that would not be worth the trouble.<br />
<br />
As we've already seen, <a href="http://sheeslostknowledge.blogspot.fr/2014/02/connecting-to-game-accessing-dde.html">sending CAOS commands to C1 and C2 games</a> is easy <a href="http://sheeslostknowledge.blogspot.fr/2014/02/connecting-to-creatures-dde-interface.html">from your favorite programming languages</a>.<br />
Then, it's just a matter of sticking this piece of code into a timer loop to get a pretty useful tool.<br />
<br />
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvxfROnIsSRLFX7IlRN_u0GuloEhgqeR4T89zEEBOv7ZHj7WygIn97nH6oIx2IhZfCYikoQNUy_fJxPxWunjOUDGnUaxcfZ3XS2THVtMlI8q56Ify0qSt1VVJd9SJczjZx-ESiRGC6aAkW/s1600/c2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvxfROnIsSRLFX7IlRN_u0GuloEhgqeR4T89zEEBOv7ZHj7WygIn97nH6oIx2IhZfCYikoQNUy_fJxPxWunjOUDGnUaxcfZ3XS2THVtMlI8q56Ify0qSt1VVJd9SJczjZx-ESiRGC6aAkW/s1600/c2.PNG" /></a></div>
<br />
<br />
<br />
Initially, such a tool was part of the Creatures Kontrol Center app I was working on, but due to delayed development on it, and the immediate usefulness of a classifier identifier tool, I decided I would publish a small standalone version of it right now.<br />
<br />
You can <a href="https://drive.google.com/open?id=0B9mJUJuZTR2EY3VjeU5RcEV4OHc&authuser=0">grab the tool here</a>.( You will need to have the <a href="https://support.microsoft.com/en-us/kb/192461">Visual Basic 6 runtime files</a> for it to work, so grab those if you run into problems when running the exe.)<br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"></span><br />
<span style="font-family: inherit;"></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;"></span></span>The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com2tag:blogger.com,1999:blog-1790862754650770452.post-65207540188295386782015-05-22T13:15:00.000+02:002015-05-28T15:24:51.251+02:00A smart(-ish) C1 scriptorium browser.<br />
One of the hard aspects of trying to understand the C1 internals is trying to figure out which scripts exist for a given object.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpTOMf-6R3lJ9W0dMjx0QErkjOPx4ThLu-6BbQmZrODKFDG4kmlQvdhN-iKe1f4BYhlzYSxNiow99UohLR6WMVvF-BG1lujW4bf9lNfZoJJpNBcDN3R4sh5xEeMve1b2BXB317lF-T0VY7/s1600/Intro.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpTOMf-6R3lJ9W0dMjx0QErkjOPx4ThLu-6BbQmZrODKFDG4kmlQvdhN-iKe1f4BYhlzYSxNiow99UohLR6WMVvF-BG1lujW4bf9lNfZoJJpNBcDN3R4sh5xEeMve1b2BXB317lF-T0VY7/s320/Intro.PNG" width="320" /></a></div>
<br />
<br />
C2 and C3, both have "Scriptorium browsers" available, that make it easy to visually browse ALL existing scripts for given classifiers.<br />
<br />
Surprisingly, C1 seems to lack such a tool, and leaves us with no easy way to be sure we found all scripts governing a given object or behaviour.<br />
<br />
Why is that so ? On what mechanisms do those scriptorium browsers operate ? And what can we do about it ?<br />
<br />
Follow me for some technical exploration of the mysterious Shees CAOS library, and if you bear with me to the end of the article, a proper, exhaustive C1 scriptorium extractor will be the takeaway :)<br />
<br />
<br />
<a name='more'></a><br />
<h3>
</h3>
<h3>
The scripts basics:</h3>
As you already now, all "things" within a Creatures world, are <a href="http://creatures.wikia.com/wiki/Classification_system">arranged into broader families</a> that represent their appartenance.<br />
Those classifiers are written as a series of 3 values, representing the object's or creatures family,genus, and specie.<br />
<br />
For each of the classifiers, there are 255 slots that can contain a script.<br />
Some of those slots numbers have special meanings, and are triggered by the game itself to produce effects of the various creatures or cobs.<br />
<br />
For example the "2 6 3" classifier corresponds to a C1 carrot (and translates as the "Simple"->"Food"->"Carrot" branch).<br />
<br />
I use a small CAOS command I call the "Show me one" to easily identify which object corresponds to a given classifier (X Y Z being the classifier you're interested in) :<br />
<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">rtar X Y Z,sys: camt,sys: edit posl post posr posb </span></span><br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk5bSneqFbwAHOE9mld7kzHqVYxhzv9G9SC3iE3EoesWdNrur_jlTAHcUL883GeEbCYEJEXG2Fglf_cYINv_pBfG26Tm2KxjLz59PRKlvkTJvsa0ju9h8MMA-nXOolMzVkMzBd09zfRO2m/s1600/carrot.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk5bSneqFbwAHOE9mld7kzHqVYxhzv9G9SC3iE3EoesWdNrur_jlTAHcUL883GeEbCYEJEXG2Fglf_cYINv_pBfG26Tm2KxjLz59PRKlvkTJvsa0ju9h8MMA-nXOolMzVkMzBd09zfRO2m/s400/carrot.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The command picks a random object of the given classifier, centers cam on it, and circles it in pink so you now where to look at.</td></tr>
</tbody></table>
<br />
<br />
The "1" script number is the universal script for "Activate1".<br />
<br />
Therefore, if we retrieve the script number "2 6 3 1" we can now know what happens when a carrot gets activated.<br />
<br />
This is cool and all, but it only works if you are targeting a known event for a known object.<br />
How would we know if there were undocumented events available ?<br />
What if you don't know the exact object you are looking for ?<br />
The various games contain numerous scenery, or background or invisible objects. Some of them do stuff you can't easily guess about while some seem to but don't.<br />
How do we find out? <br />
<br />
For this, we need a way to EXHAUSTIVELY browse all scripts for given classifiers.<br />
<h3>
</h3>
<h3>
</h3>
<h3>
How a C2/C3 Scriptorium browser works:</h3>
As most of Creatures related tools, a scriptorium browser can be implemented by sending the game the appropriate CAOS commands.<br />
<br />
Here are the relevant <a href="http://www.gamewaredevelopment.com/downloads/cdn/creatures_caos_guide.pdf">Creatures 2 commands</a> that allow implementing a scriptorium browser.<br />
<br />
<div style="margin-bottom: 0cm;">
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">TOTL </span></span><i><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">family genus species</span></span> </i>: Returns the number of objects in the
world that fit this specifier</div>
<div style="margin-bottom: 0cm;">
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">DDE: GIDS ROOT</span>:</span> Returns a list of all the Family
numbers that exist, separated with a space.</div>
<div style="margin-bottom: 0cm;">
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">DDE: GIDS FMLY </span></span><i><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">number</span></span>: </i>Returns a list of all genuses that
exist from within a certain family <i>number.</i></div>
<div style="margin-bottom: 0cm;">
<i>
</i></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">DDE: GIDS GNUS </span></span><i><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">family number</span></span>:</i> Returns a list of all species that
exist from within a certain <i>family</i> and genus <i>number</i></div>
<div style="margin-bottom: 0cm;">
<i>
</i></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">DDE: GIDS SPCS </span></span><i><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">family genus number</span>:</span> </i>Returns a list of all events that exist
from within a certain <i>family genus </i>and species <i>number</i></div>
<div style="margin-bottom: 0cm;">
<i>
</i></div>
<div style="margin-bottom: 0cm;">
<span style="color: #fce5cd;"><br /></span></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">DDE: SCRP </span></span><i><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">family genus species event</span></span>:</i> Fetches a script from the scriptorium
matching this specifier.</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">SCRP </span></span><i><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">family genus species event</span></span> : </i>Install the rest of the Macro as the script for the given event</div>
<div style="margin-bottom: 0cm;">
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;">SCRX</span></span><i><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #fce5cd;"> family genus species event</span>:</span> </i>Removes the script matching this classifier from the scriptorium.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
Armed with all those commands, implementing an exhaustive and fast scriptorium browser is trivial:</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
- First, use the "DDE: GIDS ROOT" command to get a list of all used family numbers</div>
<div style="margin-bottom: 0cm;">
- Then, for each number of this list, use "DDE: GIDS FMLY" to get the list of all existing genuses for all existing families.</div>
<div style="margin-bottom: 0cm;">
- Then again, use "DDE: GIDS GNUS" on all items of the list to get the list of all species that exist for all genuses, for all families.</div>
<div style="margin-bottom: 0cm;">
- You get the drill, then it's "DDE: GIDS SPCS" ran for all known species, to get a list of all events that are associated with those known species.</div>
<br />
You now have a complete, list of all scripts loaded inside the game, and only those.<br />
<br />
From there it's just a matter of iterating through your list of classifiers and retrieving them with the "DDE: SCRP" command.<br />
<br />
Easy enough, right ?<br />
<br />
<br />
<br />
<h3>
The Creatures 1 problem:</h3>
As of today, tools have been made that exploit most of exploitable commands available through the CAOS language. <br />
Implementing a C2 scriptorium browser is trivial, and a logic thing to do to be able to more comfortably explore the game inner workings.<br />
<br />
Then why hasn't anybody ever bothered making one for Creatures 1 ?<br />
<br />
The answer is simple.<br />
<br />
The Creatures 1 CAOS interpreter lacks all the "DDE: GIDS * " commands.<br />
The game just doesn't provide you with any means of obtaining a list of all installed families, genuses, species or events.<br />
<br />
Since you can't obtain a sure list of what exists and what does not, how could you know the list of scripts on which to run the "DDE:SCRP" to retrieve them ?<br />
<br />
Are we bound to use "dumb" C1 scriptorium browsers that always list 255 of everything and let you manually sift through 90% emptiness ? <br />
<br />
<br />
<br />
<h3>
Implementing a C1 Scriptorium browser anyway:</h3>
Since the Creatures 1 engine doesn't provide us any tools to build a precise list of existing scripts, how could we establish it anyway ?<br />
<br />
The first thought, quick and dirty approach would be to :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipYBtFfK9k1CCUJjMbRI4HA0AqPwQ8XDXBMUPeYVZfz4UFKs9mrV5ogdUP76a5u7iowyxuzY_scsOe7GntBjbGfFGIvO09dIP527cntg8bnUdR3EK3rKTvanBQqP3NTuKVjKUgh0CWcJzc/s1600/62399248.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipYBtFfK9k1CCUJjMbRI4HA0AqPwQ8XDXBMUPeYVZfz4UFKs9mrV5ogdUP76a5u7iowyxuzY_scsOe7GntBjbGfFGIvO09dIP527cntg8bnUdR3EK3rKTvanBQqP3NTuKVjKUgh0CWcJzc/s200/62399248.jpg" width="200" /></a></div>
<br />
<br />
What if we just tried to query all possible events for all possible species for all possible genuses, for all possible families ?<br />
The length of this last sentence should be the giveaway.<br />
<br />
There are 255 potential families, within which are 255 potential genuses, each potentially containing 255 species, each of them potentially having 255 event scripts.<br />
<br />
To query them all would require 4228250625 successive calls to "dde: scrp".<br />
I'll spare you the calculations: it would take a couple days, assuming an optimised and quick way of sending the commands to the game.<br />
<br />
Ok, I will admit it.At some point I thought I could get away with that approach and just let the extraction run for a couple of days.<br />
The result is that even if you chose that option, the Creatures dde engine just doesn't support such an aggressive and long querying sequence and silently just stops answering after a couple hundred thousand calls before you even get to the most interesting scripts.<br />
<br />
<br />
<br />
<h3>
Being smarter about it</h3>
What now?<br />
We will need to be slightly smarter about it.<br />
<br />
How could we cut down that huge number of calls ?<br />
Despite not providing the "DDE: GIDS *" commands, the Creatures 1 engine still provides the "TOTL" one.<br />
<br />
-This command allows us to count how many objects of a given classifier exist in the world.<br />
-We can use 0's as wildcards to specify "all of this branch".<br />
-But unfortunately this doesn't allow us to count how many scripts are installed for a given specie.<br />
<br />
Although it doesn't give us an exhaustive list right away, it will allow us to significantly cut down our number of tries.<br />
<br />
4228250625 potential scripts might seem like a huge number of potential scripts, fact is that this library is veeeeeery sparsely populated, and that most of the game scripts are concentrated in a few "regions". Most, if not all scripts are in the Creatures, foods, toys and transporters branches, as well as some scenery stuff.<br />
<br />
By simply identifying empty families/genuses/species, we already can avoid needlessly scanning huge chunks of the library.<br />
<br />
The approach isn't perfect by any means, as for example, if you tried this on an empty world with no creatures, the "Totl" for the Norn specie would be 0, and we would therefore not obtain any Norn related script.<br />
<br />
We will have to accept this fact, and consider that any realistic C1 scriptorium browser will only allow us to show scripts for all items that do exist in game at a given moment.But that's still better than nothing.<br />
<br />
The procedure to extract the C1 scriptorium then becomes:<br />
<ul>
<li>Pause the game (we really don't want the number of existing objects to vary during our extraction.)</li>
<li>Iterate through the 255 possible level 1 families with the "TOTL" CAOS command (0 0 0, to 255 0 0)</li>
<li>Discard all families that reported 0 members, keep the other ones.</li>
<li>For each Family having members , iterate through the 255 possible level 2 genuses with the "TOTL" command until we find enough to match the number of expected members for this family. Again, discarding all branches that announced having 0 children.</li>
<li>Once again, running the "TOTL" command on all 255 possible species, on the established list of genuses that have more than 0 members.Always stopping as soon as we found as much child nodes as the parent category is expected to have.</li>
<li>We end up with a list of all species that exist in our current game.No more shortcuts, we will now need to iterate over all 225 possible scripts for each item of this list and try to fetch them with the "DDE: SCRP" command to see if they exist.That is because we really want to be sure no "hidden" action slots exist.For a consumer grade application we could make some more assumptions as to script number ranges that just aren't ever used.</li>
</ul>
This should give us a pretty reasonable list of most of the game scripts (keeping in mind the mentioned limitations).One that is as good as it gets without further human tuning that is.<br />
<br />
<br />
<h3>
Closing thoughts </h3>
<br />
As always, you can find the python script used to illustrate this concept on <a href="https://github.com/LoneShee/SLKExamples/blob/master/C1_Smart_ScriptoriumExtractor.py">the site's github</a>.<br />
I also put up a compiled version of the script <a href="https://drive.google.com/open?id=0B9mJUJuZTR2EUFphYWdyUlpjUHc&authuser=0">here</a>. So you can use to extract all scripts from your game yourself.<br />
<br />
<strike>Expect at least 1 hour operation for it to complete.</strike><br />
It seems that the release version works in under 2 minutes in a real environnement :)<br />
<br />
It will dump all scripts inside a directory as separate text files named after the script classifier.<br />
<br />
Let me know if you run into any trouble trying the executable versions of the scripts.<br />
<br />
<br />
<br />The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com6tag:blogger.com,1999:blog-1790862754650770452.post-86420767615097783832014-12-24T14:15:00.001+01:002014-12-24T14:15:43.263+01:00Parsing the Creatures 1 Graveyard file <br />
One more victim of my file format reversing spree : the "The Graveyard" file containing all entries of C1 cemetery.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5_r4mQGuIf5zRuCq7GCHopq_f6X62nFyVicQMpwQbYE_RIL0-xGDVL_iX2gNTnn-DjC48PwnxeClDP5ZoneDeoV6y6AU5jZHfvrzpi0IB1UWUM4jObQDRYiKyXUb32POZD66POZoZYFrg/s1600/title.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5_r4mQGuIf5zRuCq7GCHopq_f6X62nFyVicQMpwQbYE_RIL0-xGDVL_iX2gNTnn-DjC48PwnxeClDP5ZoneDeoV6y6AU5jZHfvrzpi0IB1UWUM4jObQDRYiKyXUb32POZD66POZoZYFrg/s1600/title.PNG" height="243" width="400" /></a></div>
<br />
<br />
Parsing it will allow us to retrieve/edit/add all entries from this game file.<br />
<br />
<a name='more'></a><br />
<br />
<h4>
The file:</h4>
<h4>
</h4>
Creatures 1 cemetery information is stored in the "The Graveyard" file.<br />
It's format is once again easily understandable if you took the time to reverse engineer other game formats.<br />
<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcYhypxlNy7AKRJYGkE68SE9q7GijB3lviCn5U_fPq4Qs0BDTOVBWzshqWOGQhVHlQ2LUrW3k-n7M3CdV5yhIcFSHPj6vMdJ5MBELeZ7NwciyJF0z9rdPypEVyazu0XEupwLM8Co7O6lbM/s1600/1.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcYhypxlNy7AKRJYGkE68SE9q7GijB3lviCn5U_fPq4Qs0BDTOVBWzshqWOGQhVHlQ2LUrW3k-n7M3CdV5yhIcFSHPj6vMdJ5MBELeZ7NwciyJF0z9rdPypEVyazu0XEupwLM8Co7O6lbM/s1600/1.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The beginning of the file...</td></tr>
</tbody></table>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy2Jixf42KqrATzE1ZvAMXjP7YkBrWncoqqWfOjB8n_aSLpaD3OQbJCBgZk6tD3IvcTt7O3QcfA-aC9M0k_usOHUYtdkrD8Z3fGczaLCjwEQc_XzQLKBRRUYoM7fO6a_00sl7zQbARm_4o/s1600/2.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy2Jixf42KqrATzE1ZvAMXjP7YkBrWncoqqWfOjB8n_aSLpaD3OQbJCBgZk6tD3IvcTt7O3QcfA-aC9M0k_usOHUYtdkrD8Z3fGczaLCjwEQc_XzQLKBRRUYoM7fO6a_00sl7zQbARm_4o/s1600/2.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">... and the end of the first entry (notice empty epitaph)</td></tr>
</tbody></table>
<br />
<br />
<br />
<h4>
The file format:</h4>
<h4>
</h4>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0vSXWU4z_6_e4FOdS_FEoRelLMPUep5aDyASqhVuU0xDJ6cecWWLrQI_yjSuMnq1LakbM6YarFs0BHmSb9Ff2cJ6Lb51D1OUZbXspV1WC1gnEjzKOh32ErErAyGZP2C93Ol_xPN_b2xXd/s1600/format2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0vSXWU4z_6_e4FOdS_FEoRelLMPUep5aDyASqhVuU0xDJ6cecWWLrQI_yjSuMnq1LakbM6YarFs0BHmSb9Ff2cJ6Lb51D1OUZbXspV1WC1gnEjzKOh32ErErAyGZP2C93Ol_xPN_b2xXd/s1600/format2.png" height="158" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Overall file layout</td></tr>
</tbody></table>
<br />
<br />
Where each entry is of the following format:<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcv5zgooGV1rOUA3fa2Es6OJ9GobBo88NUIMWOCPdW1gBNpZE4DZy4PDAzulH7WKA_KYhZBd6SYK9nWwN5ypYk4la02nCXwtY9K3vz4N98nDjI3XrylRm3rdGH8-N0UFbrfUQbzRN5SKci/s1600/graveyard.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcv5zgooGV1rOUA3fa2Es6OJ9GobBo88NUIMWOCPdW1gBNpZE4DZy4PDAzulH7WKA_KYhZBd6SYK9nWwN5ypYk4la02nCXwtY9K3vz4N98nDjI3XrylRm3rdGH8-N0UFbrfUQbzRN5SKci/s1600/graveyard.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Grave entry detail</td></tr>
</tbody></table>
<br />
<br />
There you have it.<br />
You can now parse and manipulate graveyard entries at will.The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-27240861726540009072014-12-23T20:14:00.000+01:002014-12-23T22:29:51.778+01:00Understanding in game stores (Doctor's page and Aprodisiacs). aka "Health" and "Aphro" files.There are two "stores" in Creatures 1, at least that's how I call them.<br />
<br />
Those are the panels allowing you to inject additional items to the world through the Doctor's page and the aphrodisiacs page from the reproduction kit.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3k8Er9YBi3b2sKl6oWOweXTNrkRyRmz5RJkK2BWsHCzCku8XyJSLdqgsA6RzYTqdNu559m4qs56vDGGouRyAT6N36kTUXEQxrYwAPqf5pA7FAYngyff9MzhLwa2sLxfGyAz8zVisdvPTb/s1600/strores.TIF" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3k8Er9YBi3b2sKl6oWOweXTNrkRyRmz5RJkK2BWsHCzCku8XyJSLdqgsA6RzYTqdNu559m4qs56vDGGouRyAT6N36kTUXEQxrYwAPqf5pA7FAYngyff9MzhLwa2sLxfGyAz8zVisdvPTb/s1600/strores.TIF" height="337" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The C1 "Stores"</td></tr>
</tbody></table>
<br />
In this post I will show you reversing of those stores file formats, so we can replenish, parse, and edit them.<br />
<br />
<a name='more'></a><br />
<br />
<h4>
The files and their backups</h4>
<h4>
</h4>
The data for both those stores is kept in the "Health" and "Aphro" files, in the game main directory.<br />
<br />
Note that the "HealthBU" and "AphroBU" files are clean backups of those.<br />
Whenever you use the backup kit to restore their contents, the files are deleted, and replaced by the "BU" files.<br />
<br />
So what's inside ?<br />
Thanks to our previous knowledge of various file formats, and especially <a href="http://sheeslostknowledge.blogspot.fr/2014/12/repairing-and-understanding-lost-dde.html">raw image files</a>, understanding those is now a breeze.<br />
<br />
<br />
<br />
<h4>
Reversing the file format:</h4>
<h4>
</h4>
At this point I will spare you the very details of the process as you should've become pretty familiar with reversing file formats if you've read my other articles on the topic.<br />
The idea is the same as always:<br />
<ul>
<li>pick the file, </li>
<li>study game panel that seems to manipulate it to guess what data might be in there,</li>
<li>Identify known structures</li>
<li>Compare found values with values shown inside the kits</li>
<li>Manipulate fields to see how they impact the file, and the other way round. </li>
<li>Test our findings!</li>
</ul>
The following are my annotations from reversing the "Health" file:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkEhKo7hKhGrYQDpi96Q3ZhYWNJFU9FYxaWtCoFTo4r9rY3xHuubGnev770PMgB5Gl-bG48GA9-xHRkjp0mvUIktQPRHWF4enVrXKT8wGrkmauHb6j4psX6WPigwXMS8CCncwN3cVMCLhj/s1600/1.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkEhKo7hKhGrYQDpi96Q3ZhYWNJFU9FYxaWtCoFTo4r9rY3xHuubGnev770PMgB5Gl-bG48GA9-xHRkjp0mvUIktQPRHWF4enVrXKT8wGrkmauHb6j4psX6WPigwXMS8CCncwN3cVMCLhj/s1600/1.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The beginning of the file...</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgemr0QnTL1II1zrV0cQNoYBJKucZmeEEX9juTNwAzkz5-ZTT0GJJAbnxuMGJrfWnc2abgqp9z8V7iEF1IkYMV820DvR_6B_Jvm40wBSSbEriwaIVmo1K91o_NN7Dlqu5JjT5pNR7v-y-zb/s1600/2.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgemr0QnTL1II1zrV0cQNoYBJKucZmeEEX9juTNwAzkz5-ZTT0GJJAbnxuMGJrfWnc2abgqp9z8V7iEF1IkYMV820DvR_6B_Jvm40wBSSbEriwaIVmo1K91o_NN7Dlqu5JjT5pNR7v-y-zb/s1600/2.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">... and the end of the first record.</td></tr>
</tbody></table>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
Pretty straightforward wasn't it?<br />
The contents of the "Aphro" file are of the same format.<br />
<br />
<br />
<h4>
The "Health" and "Aphro" file format:</h4>
<br />
The following schemes sum up the file format.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilwP1y2dHzQcQIjVph4hR3jkXYyKIhlJh8dh0qUS_a10MC2cuwfyZY4hagTGbY30uCsFuVslJCDbOaS-ytpIb-rzW3x7gIhHk-HtZfdTfLJHaNOorCyb1_AM9_nhKi0Gugr_xTR8tUayhj/s1600/store1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilwP1y2dHzQcQIjVph4hR3jkXYyKIhlJh8dh0qUS_a10MC2cuwfyZY4hagTGbY30uCsFuVslJCDbOaS-ytpIb-rzW3x7gIhHk-HtZfdTfLJHaNOorCyb1_AM9_nhKi0Gugr_xTR8tUayhj/s1600/store1.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Overall file layout</td></tr>
</tbody></table>
<br />
Where each Item entry is of the form:<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjipU3Nkk3v0vwEGIr3tzAT-n0Ewr2Lr0up67h69ZfIY-v5wxzhVr1J2_lPS1TFYAOlyDzl5gR78rN3mYGaDF_C3437i3jjuhblb9GXWswX44CbEENlHzKzAywnpR8_qV9T_qdgwEldnUMJ/s1600/stores.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjipU3Nkk3v0vwEGIr3tzAT-n0Ewr2Lr0up67h69ZfIY-v5wxzhVr1J2_lPS1TFYAOlyDzl5gR78rN3mYGaDF_C3437i3jjuhblb9GXWswX44CbEENlHzKzAywnpR8_qV9T_qdgwEldnUMJ/s1600/stores.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Entry detail</td></tr>
</tbody></table>
<br />
<br />
And Picture data is the raw data of the corresponding sprite.<br />
Note that this gives us the opportunity to use pictures for the kit that are different from the actual in-game item.<br />
<br />
<br />
<h4>
Making use of the information:</h4>
<br />
Now we understand how those stores work, let's confirm we can indeed produce valid files.<br />
To add an item, we simply need to modify file header to count 1 more item than what it was previously, and craft a valid item entry to be appended at the end of the file.<br />
<br />
Let's keep things simple and just mimic the injection of a honey jar.<br />
We can copy most of required information already made for us from a Honey Jars.cob file for a standard honey pot ( injection script, image data...).<br />
<br />
If you ever mess the file too badly, chances are the kit will restore it automatically for you.<br />
Otherwise, you can just recover it from the "HealthBU" file. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3Lh95ulbIkGuM4OAltt5U8G3q-1sJbDfEYrLqehRkiplPwuwn0AHWGZZNk0tLR8bFVKnazSrrQErggwNW7mP0UeT1HXLcCxkNsA9rjVKJBoMbmEQdS5-CqVJQc7i4TH_AzK7UEx9dPZG4/s1600/Honey.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3Lh95ulbIkGuM4OAltt5U8G3q-1sJbDfEYrLqehRkiplPwuwn0AHWGZZNk0tLR8bFVKnazSrrQErggwNW7mP0UeT1HXLcCxkNsA9rjVKJBoMbmEQdS5-CqVJQc7i4TH_AzK7UEx9dPZG4/s1600/Honey.PNG" height="256" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">It works!</td></tr>
</tbody></table>
<br />
<br />
So what can we do with today's learned information?<br />
<ul>
<li>Restore the game stores from the "HealthBU" and "AphroBU" files if our run empty</li>
<li>Change quantity of injectable items by editing the corresponding field in the right file</li>
<li>Add arbitrary items to the game stores for easier access than through the Injector kit for commonly used items</li>
<li>Parse the Health and Aphro files to display similar content in our own third party kit.</li>
<li>Correct translation errors (Available patches seem to mess up my French install of the game by using English terms here and there after an update)</li>
</ul>
<br />
See you next time for some more file format voodoo :)<br />
(We will talk about graves, yay !)The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-73644579398182852842014-12-21T18:37:00.000+01:002014-12-21T18:37:44.230+01:00Parsing the Creatures 1 "TheRegister" file. (extracting Norn birthdates and owner information).This will be a real quick article about parsing the Creatures1 "TheRegister" file.<br />
This is like a primitive version of the <a href="http://sheeslostknowledge.blogspot.fr/2014/01/parsing-c2-histfiles.html">C2 history files</a>. It's the file that holds all creature information saved when you register a creature's birth. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHirKrzWSmNnRWPJx38-MInX3-k6EbbRm6GB4vLGFnGS89or9vfT9DwL9fbV2kxsVA07h5dfSCMVY9Proqr3GD6YXp6kEfbuoNFh-crasDYoJs0WjFklRvhKRc0Hokmfr-VEDq1NX6MTD8/s1600/Intro.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHirKrzWSmNnRWPJx38-MInX3-k6EbbRm6GB4vLGFnGS89or9vfT9DwL9fbV2kxsVA07h5dfSCMVY9Proqr3GD6YXp6kEfbuoNFh-crasDYoJs0WjFklRvhKRc0Hokmfr-VEDq1NX6MTD8/s1600/Intro.PNG" height="246" width="400" /></a></div>
<br />
<br />
They contain information about the Norn such as name, parents, date of birth and all owner info.<br />
<br />There's nothing really fancy about reversing and understanding the file format, so let's get this done.<br />
<br />
<a name='more'></a><br /><br />
<h4>
Reversing the file format.</h4>
TheRegister is one of the easiest files to understand.<br />
Let's first register a Norn's birth by fully filling all fields so any guesswork is taken out of the process:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh98l9a3Zdlhv2Yr8Z7YjdZF1KDyoLmi-iPIgPim52zUz1DM6yeUTHZRjhAKcOv5PSBnM4blg4SfRcD-jjRdBd76Nu9xTnjlpQy5_rTNd7i69HNszfASEr6fseFdnr_m4avP3BB-XJHjDGQ/s1600/details.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh98l9a3Zdlhv2Yr8Z7YjdZF1KDyoLmi-iPIgPim52zUz1DM6yeUTHZRjhAKcOv5PSBnM4blg4SfRcD-jjRdBd76Nu9xTnjlpQy5_rTNd7i69HNszfASEr6fseFdnr_m4avP3BB-XJHjDGQ/s1600/details.PNG" height="320" width="275" /></a></div>
<br />
And open TheRegister file in a hex editor:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbu1zYxEfoqS3yLc-djRrx9UmIox8LDVw040UvaKyvAL5GUCPWTDH_GK2xE_ZaP9ZgAwnSNI4g_2J43Riz20aqLJr8tCnbWjYVrhXCf70t2fLZNIxEKl2VzxLY6ZXcO_ro-gDYe0NNwJi6/s1600/file.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbu1zYxEfoqS3yLc-djRrx9UmIox8LDVw040UvaKyvAL5GUCPWTDH_GK2xE_ZaP9ZgAwnSNI4g_2J43Riz20aqLJr8tCnbWjYVrhXCf70t2fLZNIxEKl2VzxLY6ZXcO_ro-gDYe0NNwJi6/s1600/file.PNG" height="213" width="400" /></a> </div>
<br />
The first thing we notice is that most recent entries are at the top of the file.<br />
<br />
The meaning of all fields is then pretty intuitive, as apart from a 2byte header, the whole file is just a series of Cstrings.<br />
<br />
It is easy to match them to data from the file:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNHd5MqHyvlKS4-Eig4oyS5YWpmAyL3WqEAI-0sY5cH3_Ka6LSB_SJmGSME1clSA1tFBrFKZ3V0xfGaWwANNb2vAETjnXG7np32yvyfnquRI8oEcoEKoeFSyM4ed3ejvbPw3OQbEJuo0mM/s1600/Format.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNHd5MqHyvlKS4-Eig4oyS5YWpmAyL3WqEAI-0sY5cH3_Ka6LSB_SJmGSME1clSA1tFBrFKZ3V0xfGaWwANNb2vAETjnXG7np32yvyfnquRI8oEcoEKoeFSyM4ed3ejvbPw3OQbEJuo0mM/s1600/Format.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Format for first entry is described here, the rest is just a series of similar entries.</td></tr>
</tbody></table>
<br />
<h4>
Summary:</h4>
The format of the Creatures 1 "The Register" file is:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKsQ8nHTKNad52WWb4criTrdXFSRIMaRPkpHHRhv24Zyl4kvWqy8ES1j6Cb6o06L4YyCGYvmYPmosFcofBwshEE2GOEOSlDjUnyxrNqnNmn-xVi2O23E3DMTDW9ip7z0Krlo2v4Kq1yQBx/s1600/Highlevel.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKsQ8nHTKNad52WWb4criTrdXFSRIMaRPkpHHRhv24Zyl4kvWqy8ES1j6Cb6o06L4YyCGYvmYPmosFcofBwshEE2GOEOSlDjUnyxrNqnNmn-xVi2O23E3DMTDW9ip7z0Krlo2v4Kq1yQBx/s1600/Highlevel.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS4qaitrg_7QDYQ5WmxMNeEiQIeOK8eKI3pZx0vMvdBn-DmmLcq5TAHt9i5UiKNi5EOQmcAUQoOQtkdr1-xK_mWFgkcXu23QS2CaC-wRTm53MUoByQtfeSgjfhytTcPm-onfJwQ4ajg1h3/s1600/table.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
Where each entry is of the following form:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd34YIwqc9Bb7R_Fj3-6fQqeB7NeJqhc8e9WU8Bdf3w6l_09LsbQ9tooW4Y2NNrVg1hOFf8J77ZsjzQ6W0Y33J7QTvZTVvczCHPcNBwrdr5iflZuNM8Yixe4xTKthjL_bivInmZsx2Zevr/s1600/Entry.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd34YIwqc9Bb7R_Fj3-6fQqeB7NeJqhc8e9WU8Bdf3w6l_09LsbQ9tooW4Y2NNrVg1hOFf8J77ZsjzQ6W0Y33J7QTvZTVvczCHPcNBwrdr5iflZuNM8Yixe4xTKthjL_bivInmZsx2Zevr/s1600/Entry.png" height="320" width="182" /></a></div>
<br />
<br />
Be careful when parsing this file, as I noticed that similarly to the PhotoAmbum files, this file tends to get corrupted if you perform multiple rewrites on it from inside the game (by registering a creature multiple times and/or without names for example)<br />
<br />
<br />
I hope I didn't bother you too much with this one.<br />
There are still a couple more file formats we will learn to parse in the near future.<br />
<br />The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-54805352521183971672014-12-17T23:59:00.003+01:002014-12-22T13:20:28.941+01:00Investigating Creatures 1 TeleportersAlright, despite having loads of stuff in store, maybe I'll take a break from gory reversing stuff for this post, before I loose all of my readers (yeah, something like "both of them") :)<br />
<br />
So why not take this opportunity to study something more generic? what about investigating how C1 teleporters work?<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-ZDSsD1A9wb3mPAHCSaPnHszDWvclyqzNkwx2DuslySnxohJZTLEskO03tB3qMgySd6KWqvzzEpArsGef7yNJz87taoqAr43Si0XP3FrM7GqMRWCDYqrSrJroRwLoAdsP8jKGaoBbg9HH/s1600/family.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-ZDSsD1A9wb3mPAHCSaPnHszDWvclyqzNkwx2DuslySnxohJZTLEskO03tB3qMgySd6KWqvzzEpArsGef7yNJz87taoqAr43Si0XP3FrM7GqMRWCDYqrSrJroRwLoAdsP8jKGaoBbg9HH/s1600/family.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A happy Norn family, ready for exploration of time and space.</td></tr>
</tbody></table>
<br />
<br />
<br />
It only requires a bit of CAOS reading and your favorite <a href="http://double.co.nz/creatures/brainutilities.htm">C1 CAOS tool</a>.<br />
<a name='more'></a><br />
<h4>
</h4>
<h4>
Getting the information</h4>
As you probably know by now, in all creatures games, all things are <a href="http://creatures.wikia.com/wiki/Classification_system">classified in broader families</a> addressable by a 3 number identifier.<br />
<br />
In this classification, C1 teleporters belong to the "Compound objects -> Vehicle -> Teleporter" branch.<br />
Translated into CAOS terms, this is the "3->1->1" classifier.<br />
<br />
If in doubt you can use the following command to explore what a given classifier corresponds to:<br />
<br />
<span style="color: #f1c232;"><span style="font-family: "Courier New",Courier,monospace;">rtar 3 1 1,sys: camt</span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEF8exGsUAy8i-ME3Jgi-dtYfWcgx1dJXVWEzT5s1Gr3rllPvBJhtL2Xy05J4V5Cz0kJVRsJcj6Eb_PJNPmSDD2g5tay3Ak6MyUfv4K9thT-fsEYbt70XtL8vghuCy2HUC5V-9m2eDAI9P/s1600/rtar.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEF8exGsUAy8i-ME3Jgi-dtYfWcgx1dJXVWEzT5s1Gr3rllPvBJhtL2Xy05J4V5Cz0kJVRsJcj6Eb_PJNPmSDD2g5tay3Ak6MyUfv4K9thT-fsEYbt70XtL8vghuCy2HUC5V-9m2eDAI9P/s1600/rtar.PNG" height="226" width="400" /></a></div>
<br />
<br />
"rtar" means "Select a random target among following identifier" , and "sys: camt" centers game camera on target.<br />
You can use 0's in place of any of the numbers as a wildcard for "any".<br />
<br />
Repeatedly running those commands can quickly get you through the objects you are looking for:<br />
<br />
<ul>
<li><span style="color: #f1c232;">rtar 3 1 0,sys: camt </span>will show you all kinds of vehicles</li>
<li><span style="color: #f1c232;">rtar 2 6 0,sys: camt</span> will cycle you through all foods</li>
<li><span style="color: #f1c232;">rtar 2 6 4,sys: camt</span> will do so specifically through all the lemons</li>
<li>...</li>
</ul>
All Creatures objects also have a set of scripts associated with them.<br />
Each possible action is mapped to a script handling what will happen when the corresponding action occurs ( Actions include, enabling, carrying ,dropping, clicking,timers...)<br />
<br />
The action Number 2 corresponds to activation.<br />
We can therefore recover the script associated with teleporter activation by issuing the following CAOS command:<br />
<br />
<span style="color: #f1c232;"> dde: scrp 3 1 1 2 </span><br />
<br />
Which means "Compound objects -> Vehicle -> Teleporter->Activate2"<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj2IexM2sGIvbCAMM6kI4r8SfMlw-Q_Q6NkxCQu1hfWOOMmpravqB-146-CYyCC-yP2YspLDf3UOMaJ2eZ4lUWUqv4B1Ni2VPuWYHNhxWmgT_vnHDbdTtpynyVhovZjLc_unRyP0-vhwMx/s1600/CAOS.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj2IexM2sGIvbCAMM6kI4r8SfMlw-Q_Q6NkxCQu1hfWOOMmpravqB-146-CYyCC-yP2YspLDf3UOMaJ2eZ4lUWUqv4B1Ni2VPuWYHNhxWmgT_vnHDbdTtpynyVhovZjLc_unRyP0-vhwMx/s1600/CAOS.PNG" height="102" width="400" /></a></div>
<br />
<br />
And the command returns :<br />
<br />
<span style="color: #f1c232;"><span style="font-family: "Courier New",Courier,monospace;">setv actv 0,gpas,snde telb,snde tele,part 0,anim [123456],part 1,anim [123456],over,doif posl lt 3000,doif posl lt 1500,tele 7730 456,else tele 3992 930,endi,else,doif posl lt 5000,tele 2880 740,else,tele 1180 600,endi,endi,part 0,anim [67890],part 1,anim [67890],endm</span></span><br />
<br />
<br />
<h4>
Making sense of the script</h4>
After a bit of formatting, we get the following:<br />
<br />
<span style="color: #f1c232;"><span style="font-family: "Courier New",Courier,monospace;">setv actv 0<br />gpas<br />snde telb<br />snde tele<br />part 0<br />anim [123456]<br />part 1<br />anim [123456]<br />over<br /><br />doif posl lt 3000<br /> doif posl lt 1500<br /> <br /> tele 7730 456<br /> else <br /> tele 3992 930<br /> endi<br /><br />else<br /> doif posl lt 5000<br /> tele 2880 740<br /> else<br /> tele 1180 600<br /> endi<br />endi<br /><br />part 0<br />anim [67890]<br />part 1<br />anim [67890]<br />endm</span></span><br />
<br />
Let's comment this and take bits one by one :<br />
<br />
<span style="color: #f1c232;"><span style="font-family: "Courier New",Courier,monospace;">setv actv 0 <span style="color: #6aa84f;"># Clears the "Active" flag on the objec</span></span></span><span style="color: #f1c232;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #6aa84f;">t, see remark below</span><br />gpas <span style="color: #6aa84f;"># "Get Passengers" : loads nearby creatures into the Teleporter's field</span><br />snde telb <span style="color: #6aa84f;"># Plays the Zap sound</span><br />snde tele <span style="color: #6aa84f;"># Plays the teleporting sound</span><br />part 0 <span style="color: #6aa84f;"># Sets part 0 of the teleporter as the target for further actions</span><br />anim [123456] <span style="color: #6aa84f;"># Plays animation of teleporter part 0</span><br />part 1 <span style="color: #6aa84f;"># Sets part 1 of the teleporter as the target for further actions</span><br />anim [123456] <span style="color: #6aa84f;"># Plays animation of teleporter part 1</span><br />over <span style="color: #6aa84f;"># Waits until animation is over before continuing</span><br /> <span style="color: #6aa84f;"># Note that part 0 and 1 are run in parallel as only one<br /> # "over" command is used</span><br /><br /><br />doif posl lt 3000 <span style="color: #6aa84f;">#Enter this bloc if current object's left position is lower than 3000</span><br /> doif posl lt 1500 <span style="color: #6aa84f;">#Enter this bloc if current object's left position is lower than 1500</span><br /> <br /> <span style="color: #6aa84f;"># If both conditions are met ( posl <3000 and posl < 1500 )</span><br /> tele 7730 456 <span style="color: #6aa84f;"># Teleport to 7730 456</span><br /> else<br /><br /> <span style="color: #6aa84f;"># Otherwise, If if only posl <3000 is true (i.e. 1500<posl<3000 )</span><br /> tele 3992 930 <span style="color: #6aa84f;"># Then teleport to 3992 930</span><br /> endi<br /><br />else <span style="color: #6aa84f;"># If object position is not lower than 3000, enter this part</span><br /> doif posl lt 5000 <span style="color: #6aa84f;"># If it is >3000 but < 5000</span><br /> tele 2880 740 <span style="color: #6aa84f;"># Teleport to 2880 740</span><br /> else <span style="color: #6aa84f;"># Otherwise ( >3000 and > 5000 )</span><br /> tele 1180 600 <span style="color: #6aa84f;">#Teleport to 1180 600</span><br /> endi<br />endi<br /><br />part 0 <span style="color: #6aa84f;"># Sets part 0 of the teleporter as the target for further actions</span><br />anim [67890] <span style="color: #6aa84f;"># Plays animation of teleporter part 0</span><br />part 1 <span style="color: #6aa84f;"># Sets part 0 of the teleporter as the target for further actions</span><br />anim [67890] <span style="color: #6aa84f;"># Plays animation of teleporter part 1</span><br />endm <span style="color: #6aa84f;"> # End Macro</span></span></span><br />
<br />
<br />
<br />
The non-intuitive part here probably is usage of the "<span style="color: #f1c232;"><span style="font-family: "Courier New",Courier,monospace;">setv actv 0</span></span>" command right at the beggining of the script.<br />
This command means "Deactivate the current object".<br />
Then how using it so early doesn't break anything?<br />
In fact, this is needed to instruct the game engine that the object did finish being used so it can be activated again later.<br />
Without this instruction, the game wouldn't know when the object is done doing it's thing and you could only clik it once in it's lifetime.<br />
Using it early in the script doesn't hurt, as it doesn't interrupt the script execution.<br />
You might want to use it later in the script to prevent multiple activations of the object before it's animation/action terminates.<br />
<br />
Other than that here's not that much to it and things should be pretty clear with the above explanations.<br />
However the way teleporters are handled is interesting.<br />
<br />
<br />
<h4>
Handling multiple teleporters in one script</h4>
<br />
We can see that all 4 game teleporters are treated as one unique object, and that this only script is used to make them all work.<br />
<br />
The game uses the current object's "posl" (position of the left edge) as a means to know which of the four teleporters is the one running the script.<br />
<br />
Basically, it checks if the object running the script is below the 1500 th pixel, or between 1500 and 3000, or between 3000 and 5000, or over 5000.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhABbFt_iXtUC0-p6SD6Fa7kyCVTYIQbqC3yQoGyhvkaCPPDB0DaKe0OZDKL2F7G_z_nmudrsz0yS3Vhx8123dXaiLGftdASZCBkG7T-1L_2ekMAUelaWo4AtGn2K6weaZb-k2HEwOM7mmd/s1600/slices.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhABbFt_iXtUC0-p6SD6Fa7kyCVTYIQbqC3yQoGyhvkaCPPDB0DaKe0OZDKL2F7G_z_nmudrsz0yS3Vhx8123dXaiLGftdASZCBkG7T-1L_2ekMAUelaWo4AtGn2K6weaZb-k2HEwOM7mmd/s1600/slices.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Approximate position of the world slices and the teleporters.</td></tr>
</tbody></table>
<br />
<br />
<br />
Those correspond to very rough slices of the world but why not ? there are only 4 fixed teleporters and they are significant distance apart, so this technique makes sense as a low computing power means of attributing the action to a given teleporter.<br />
<br />
<br />
<h4>
Understanding other small bits:</h4>
We now know the broad lines of how all of this works, but we need to also get into the details to be able to say we fully mastered the teleporters inner workings.<br />
<br />
What we might want to understand now is :<br />
<ul>
<li>Which teleporter is which ? </li>
<li>How is the animation played on the remote teleporter when the Norn arrives while the target teleporter is never mentioned in the script </li>
</ul>
If we read out script " 3 1 1 1" ("Compound objects -> Vehicle -> Teleporter->Activate1"), with :<br />
<br />
<span style="color: #f1c232;">dde: scrp 3 1 1 1 </span><br />
<br />
We can see :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwtFP_8lmvRYgQ6JQQm4JliAft3o8Z4Zv4uC6ptJEuT2NUV_CfjmCJ-Jh6Im2FPEx92D9Y9Eq4eK4W_yRMxUtwcw4jUjFyAlpSJ18hg-eVayGdX1UdFrKTIoZ0iL9EeV1EfzgHYwHv3pnl/s1600/terg.TIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwtFP_8lmvRYgQ6JQQm4JliAft3o8Z4Zv4uC6ptJEuT2NUV_CfjmCJ-Jh6Im2FPEx92D9Y9Eq4eK4W_yRMxUtwcw4jUjFyAlpSJ18hg-eVayGdX1UdFrKTIoZ0iL9EeV1EfzgHYwHv3pnl/s1600/terg.TIF" height="102" width="400" /></a></div>
<br />
This means:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #f1c232;">enum 3 1 1 <span style="color: #6aa84f;"># For each 3 1 1 object (teleporter)</span><br /> mesg writ targ 1 <span style="color: #6aa84f;"># Run it's #1 action (activate)</span><br />next<br />endm</span></span><br />
<br />
Therefore, when one teleporter is activated, all of them fire, running the same animation.<br />
<br />
<br />
To know which teleporter is which, we can simply use the "sys: cmra x y" command with the coordinates of the four teleport targets and see where we land.<br />
<br />
( the "tele" command teleports a creature to a given position, the "sys: cmra" one only moves the game cam to given coordinates)<br />
<br />
We get the following results : <br />
<ul>
<li>7730 456 is the island bridge</li>
<li>3992 930 is the garden</li>
<li>2880 740 is the nursery</li>
<li>1180 600 is the light house</li>
</ul>
Notice how the X values for each of the teleporters fall within the world slices we identified earlier:<br />
<br />
<span style="color: #6aa84f;"><b>1180</b></span><1500<<span style="color: #6aa84f;"><b>2880</b></span><3000<<span style="color: #6aa84f;"><b>3992</b></span><5000<<span style="color: #6aa84f;"><b>7730</b></span><br />
<br />
<br />
<h4>
Messing with the teleporters.</h4>
Now we fully understand how all of this works, why not mess a bit around with the teleporters?<br />
Let's change their behaviour, and instead of having them work in pairs, make any teleporter send the creature to a random teleporter among the three other (we could also simply permute them,or make them teleport Norns to other places, not necessarily other teleporters). <br />
<br />
Lets do it like this :<br />
<br />
<span style="color: #f1c232;"><span style="font-family: "Courier New",Courier,monospace;">setv actv 0 <span style="color: #6aa84f;"># Clears the "Active" flag on the object</span><br />gpas <span style="color: #6aa84f;"># "Get Passengers" : loads nearby creatures into the Teleporter's field</span><br />snde telb <span style="color: #6aa84f;"># Plays the Zap sound</span><br />snde tele <span style="color: #6aa84f;"># plays the teleporting sound</span><br />part 0 <span style="color: #6aa84f;"># Sets part 0 of the teleporter as the target for further actions</span><br />anim [123456] <span style="color: #6aa84f;"># Plays animation of teleporter part 0</span><br />part 1 <span style="color: #6aa84f;"># Sets part 1 of the teleporter as the target for further actions</span><br />anim [123456] <span style="color: #6aa84f;"># Plays animation of teleporter part 1</span><br />over <span style="color: #6aa84f;"># Waits untill animation is over before continuing<br /> # Note that part 0 and 1 are run in parallel as only one <br /> # "over" command is used</span><br /><span style="color: red;">rndv var0 0 2 </span> <span style="color: #6aa84f;"># Roll a 3 sided dice ,results are 0-2 inclusive</span><br /><br /><br /><br />doif posl lt 3000 <br /> doif posl lt 1500 <span style="color: #6aa84f;"># If source is the lighthouse</span><br /> <br /> <span style="color: red;">doif var0 eq 0 <br /> tele 7730 456 <span style="color: #6aa84f;"># go to Island</span><br /> endi<br /> doif var0 eq 1 <br /> tele 3992 930 <span style="color: #6aa84f;"># go to the Garden</span><br /> endi<br /> doif var0 eq 2 <br /> tele 2880 740 <span style="color: #6aa84f;"># go to the Nursery</span><br /> endi </span><br /> else <span style="color: #6aa84f;"># If source is the Nursery</span><br /> <span style="color: red;">doif var0 eq 0 <br /> tele 7730 456 <span style="color: #6aa84f;"># go to Island</span><br /> endi<br /> doif var0 eq 1 <br /> tele 3992 930 <span style="color: #6aa84f;"># go to the Garden</span><br /> endi<br /> doif var0 eq 2 <br /> tele 1180 600 <span style="color: #6aa84f;"># go to the light house</span><br /> endi</span><br /> <br /> endi<br /><br />else <br /> doif posl lt 5000 <span style="color: #6aa84f;"># If source is the Garden</span><br /> <span style="color: red;">doif var0 eq 0 <br /> tele 7730 456 <span style="color: #6aa84f;"># go to Island</span><br /> endi<br /> doif var0 eq 1 <br /> </span></span></span><span style="color: #f1c232;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: red;">tele 1180 600 <span style="color: #6aa84f;"># go to the light house</span></span></span></span><span style="color: #f1c232;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: red;"><span style="color: #6aa84f;"></span><br /> endi<br /> doif var0 eq 2 <br /> tele 2880 740 <span style="color: #6aa84f;"># go to the Nursery</span><br /> endi</span><br /> <br /> else <span style="color: #6aa84f;"># If source is the Island bridge</span><br /> <span style="color: red;">doif var0 eq 0 <br /> tele 3992 930 <span style="color: #6aa84f;"># go to the Garden</span><br /> endi<br /> doif var0 eq 1 <span style="color: #6aa84f;"> <br /> tele 2880 740 # go to the Nursery</span><br /> endi<br /> doif var0 eq 2 <br /> tele 1180 600 <span style="color: #6aa84f;"># go to the light house</span><br /> endi</span><br /><br /> endi<br />endi<br /><br />part 0 <span style="color: #6aa84f;"># Sets part 0 of the teleporter as the target for further actions</span><br />anim [67890] <span style="color: #6aa84f;"># Plays animation of teleporter part 0</span><br />part 1 <span style="color: #6aa84f;"># Sets part 0 of the teleporter as the target for further actions</span><br />anim [67890] <span style="color: #6aa84f;"># Plays animation of teleporter part 1</span><br />endm <span style="color: #6aa84f;"># End Macro</span></span></span><br />
<br />
We can now put all of this on one horribly long line, and install the script by using "scrx" to remove the preceding, and "scrp" to install the new one:<br />
<br />
<br />
<span style="color: #f1c232;"><span style="font-family: "Courier New",Courier,monospace;">scrx 3 1 1 2,scrp 3 1 1 2,setv actv 0,gpas,snde telb,snde tele,part 0,anim [123456],part 1,anim [123456],over,rndv var0 0 2,doif posl lt 3000,doif posl lt 1500,doif var0 eq 0,tele 7730 456,endi,doif var0 eq 1,tele 3992 930,endi,doif var0 eq 2,tele 2880 740,endi,else,doif var0 eq 0,tele 7730 456,endi,doif var0 eq 1,tele 3992 930,endi,doif var0 eq 2,tele 1180 600,endi,endi,else,doif posl lt 5000,doif var0 eq 0,tele 7730 456,endi,doif var0 eq 1,tele 1180 600,endi,doif var0 eq 2,tele 2880 740,endi,else,doif var0 eq 0,tele 3992 930,endi,doif var0 eq 1,tele 2880 740,endi,doif var0 eq 2,tele 1180 600,endi,endi,endi,part 0,anim [67890],part 1,anim [67890],endm</span></span><br />
<br />
<br />
This will sure help lazy Norns to spread around the world more efficiently :)<br />
Making an emergency cob that teleports a Creature back in the kitchen is left as an exercise for the reader.<br />
<br />
See you soon !<br />
<br />
<br />
<br />
<br />The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com2tag:blogger.com,1999:blog-1790862754650770452.post-1729625576843188642014-12-14T17:55:00.000+01:002015-05-06T22:10:29.087+02:00Extracting information from Creatures 1 PhotoAlbum files (And uncovering a 20 years old 2 pixel bug :)In the <a href="http://sheeslostknowledge.blogspot.fr/2014/12/repairing-and-understanding-lost-dde.html">last article</a>, we've seen how to manually use the "dde: pict" CAOS command to take picture of our Norns the way the Owner's kit does it.<br />
<br />
When doing it the usual way through the Owner's kit, all pictures are saved in individual photo album files for each Norn.<br />
In this article I will show you all you need to know to extract all information from those file : timestamps, comments, and obviously, the picture data.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8yJ67tZD2Go-3pIHpRr5BkrxsjGRV5SG7hxa-rhsX44itm5iodedELDY80i0UgJQ4yxSIos3Ckv5XRMQFGtpnEcLysxYg2E7PURatZ4KM2WIa-8-pC1vohmf0d8aDE4tVslsw73CqSUjG/s1600/updated.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8yJ67tZD2Go-3pIHpRr5BkrxsjGRV5SG7hxa-rhsX44itm5iodedELDY80i0UgJQ4yxSIos3Ckv5XRMQFGtpnEcLysxYg2E7PURatZ4KM2WIa-8-pC1vohmf0d8aDE4tVslsw73CqSUjG/s1600/updated.PNG" height="318" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXVmBxAnXRU7uK98CWoCUE6S9IwVPsgO1IzV9zUOa5l2oYkMI9kJ8jTPUL2jj9lB4dcXeehwB0sDUkOWnV7yu07nZQv1-vKt0DnXOkbDMJdLOFbpo4xyL3VJGo5bMB2lVs2tGGO7ET5h5q/s1600/Albums.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<a name='more'></a><br />
<h4>
The .Photo Album files:</h4>
<span style="font-family: inherit;">They are found at the root of the Game main directory.</span><br />
<span style="font-family: inherit;">There is one <span style="font-family: inherit;">for each Nor<span style="font-family: inherit;">n for which you took pictures in your games.</span></span></span><br />
<span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;">They also re<span style="font-family: inherit;">main there after a Norn's death, so <span style="font-family: inherit;">it is a nice opportunity to recover pictures of dead Norns while the g<span style="font-family: inherit;">ame only allows you to<span style="font-family: inherit;"> see the last picture<span style="font-family: inherit;"> you picked for a Norn's grave<span style="font-family: inherit;">.</span></span></span></span></span></span></span></span></span><br />
<br />
<span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;">They ar<span style="font-family: inherit;">e named with a string of 4 Hexadecimal characters, follo<span style="font-family: inherit;">wed by the ".Ph<span style="font-family: inherit;">oto Album" ext<span style="font-family: inherit;">ension.</span></span></span></span></span></span></span></span></span></span></span></span></span><br />
<span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;">The 8 first character<span style="font-family: inherit;">s <span style="font-family: inherit;">are he<span style="font-family: inherit;">xadecimal repres<span style="font-family: inherit;">entation of a Norn's moniker<span style="font-family: inherit;">, and th<span style="font-family: inherit;">is is how the file are matched to a given Norn<span style="font-family: inherit;">.</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir2IZtQk0mK5kQAjCCb_Lc5R9hK4WNLOJ8b7Y2VKV-ut5J1m_7CH475By02bYSs1UA7djfbKvpvGym34oifWhgh4LEWSjNZxOvFNO-TFQ1SIRpPKmCDKIeJNIKP3q5Dqv5Hjly4avAtjZf/s1600/Albums.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir2IZtQk0mK5kQAjCCb_Lc5R9hK4WNLOJ8b7Y2VKV-ut5J1m_7CH475By02bYSs1UA7djfbKvpvGym34oifWhgh4LEWSjNZxOvFNO-TFQ1SIRpPKmCDKIeJNIKP3q5Dqv5Hjly4avAtjZf/s1600/Albums.PNG" /></a></div>
<br />
<br />
<span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;">To find which file contains <span style="font-family: inherit;">the data<span style="font-family: inherit;"> for a given <span style="font-family: inherit;">Norn, simply <span style="font-family: inherit;">pick it's moniker<span style="font-family: inherit;">, convert it<span style="font-family: inherit;">'s letters to hexadecimal and look for t<span style="font-family: inherit;">he corresponding file:</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinHMqBqGbN3UTa2aiueS5b6qUkhi8o4zOm_NtwR_14bi2R_SA8bG9djmvgkVBuiUFrAQmcYx-Ka6BIwVQ-O9I-IaDg7Vw9z9OgX8Ze4ep_Vpp49HaHVIrpmo5dPv6VZ9VJ1VlMKfSr6gy5/s1600/Moniker.TIF" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinHMqBqGbN3UTa2aiueS5b6qUkhi8o4zOm_NtwR_14bi2R_SA8bG9djmvgkVBuiUFrAQmcYx-Ka6BIwVQ-O9I-IaDg7Vw9z9OgX8Ze4ep_Vpp49HaHVIrpmo5dPv6VZ9VJ1VlMKfSr6gy5/s1600/Moniker.TIF" height="160" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">0BGE is this Norn's Moniker</td></tr>
</tbody></table>
<span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"> </span></span></span></span></span></span></span> </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>Let's translate a moniker to the corresponding string:<br />
<ul>
<li>0 = 0x30</li>
<li>B= 0x42 </li>
<li>G=0x47</li>
<li>E=0x45</li>
</ul>
The trick is the moniker is written in reverse in the file name, therefore, when looking for 0BGE's Photo album we don't want the 30424745.Photo Album, but the 45474230.Photo Album one . <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjd5di3NrX0GiYj6vsddRQJn8aSQVvlJADfDHiSiMxsrneGs7yCp8f7CX3TK71cQdpeRx0Efq6lpvxObqSsiklvtbXhyphenhyphenlEcCQ7v9cooQTnrWqUrHPXR5K6jypttY6ibdwZ5pLTIWDb5kXaA/s1600/Found.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjd5di3NrX0GiYj6vsddRQJn8aSQVvlJADfDHiSiMxsrneGs7yCp8f7CX3TK71cQdpeRx0Efq6lpvxObqSsiklvtbXhyphenhyphenlEcCQ7v9cooQTnrWqUrHPXR5K6jypttY6ibdwZ5pLTIWDb5kXaA/s1600/Found.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Here it is !</td></tr>
</tbody></table>
<br />
<h4>
Understanding the file format :</h4>
<h4>
</h4>
When we open the file in a hexadecimal editor, there are familiar things we recognize from <a href="http://sheeslostknowledge.blogspot.fr/2014/12/repairing-and-understanding-lost-dde.html">the "dde: pict" article.</a><br />
I'll spare you the whole process of reversing the file format as it's pretty easy and doesn't bring anything more than previous articles.It's mainly made of easily identifiable bits and familiar structures:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqNFDmr3Adihg-odq4ThmNnk9YmL3V1Z7Eu_EaYbDjbL5bVKtRjwD-SU_8bWGoMb592mESrz5bGaawQkkrNXle_eySb1MnIZttYweD40kQ_5pX6DQE92IaEz8_keSiktZmHl6cWuOrEMbK/s1600/Format.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqNFDmr3Adihg-odq4ThmNnk9YmL3V1Z7Eu_EaYbDjbL5bVKtRjwD-SU_8bWGoMb592mESrz5bGaawQkkrNXle_eySb1MnIZttYweD40kQ_5pX6DQE92IaEz8_keSiktZmHl6cWuOrEMbK/s1600/Format.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This is the file beginning...</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtTJz7V8X8oWug_TwQua7lmj3R_Oz9eqSeNxgIx8QJmpQq_9txOAX0aiMZTQo9fquy8dJKjfYOD6kCfJU-GD0B2LQPaaSiTULfy7jzz37N4o0iB8uvnlwKedjCeEoSUHXSv6B3I1HyaQ0Y/s1600/end+format.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtTJz7V8X8oWug_TwQua7lmj3R_Oz9eqSeNxgIx8QJmpQq_9txOAX0aiMZTQo9fquy8dJKjfYOD6kCfJU-GD0B2LQPaaSiTULfy7jzz37N4o0iB8uvnlwKedjCeEoSUHXSv6B3I1HyaQ0Y/s1600/end+format.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">And this is the end of the data section for the first picture.</td><td class="tr-caption" style="text-align: center;"><br /></td><td class="tr-caption" style="text-align: center;"><br /></td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
<br />
Pretty easy isn't it ?<br />
<br />
<h4>
The .Photo Album format explained: </h4>
<br />
We now Know the format for C1 Photo album files is read as follows:<br />
<ul>
<li>Number of pictures in album (Coded on 2 bytes)</li>
<li>A Cstring containing the Picture timestamp in a readily readable format.</li>
<li>Width of first picture coded on 4 bytes</li>
<li>Height of first picture coded on 4 bytes</li>
<li>The width of the picture again on 4 bytes, this seems to be unused and always equal to first value.</li>
<li>The picture actual data ( length is Width x Height bytes )</li>
<li>A Cstring representing the Picture's Comment (one single 00 if empty comment)</li>
<li>Repeat all above steps for reading Next picture.</li>
</ul>
<br />
The overall format is as such:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUy_JyM_mENvGnzZ66mjUIqeF0Af7lc6uCvBjtjdPc9Yx1pRR4FlXyQyERPnyozUXEUWyoSvr8dTOi-X78sWQT0uMh91aq7SNTNdgwRnhUj0HgspuVFb47uC_75nMVxJZHN9wzqH-hWKTh/s1600/format1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUy_JyM_mENvGnzZ66mjUIqeF0Af7lc6uCvBjtjdPc9Yx1pRR4FlXyQyERPnyozUXEUWyoSvr8dTOi-X78sWQT0uMh91aq7SNTNdgwRnhUj0HgspuVFb47uC_75nMVxJZHN9wzqH-hWKTh/s1600/format1.png" height="48" width="640" /></a></div>
<br />
Where data for each picture entry is decoded as follows: <br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLUFHUpF5QUctHu15vEICoHk3uawKwa6tNWsycXbGPtItPFFLIy1pe-bKYu3y7R_UswWh0EE1ITigG8pdZ1P3PYu88UNMGc0cRVpDveZ7uoLc0YvbLXCzk7_u5qkCSweynzjGqeWqqhTwW/s1600/format2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLUFHUpF5QUctHu15vEICoHk3uawKwa6tNWsycXbGPtItPFFLIy1pe-bKYu3y7R_UswWh0EE1ITigG8pdZ1P3PYu88UNMGc0cRVpDveZ7uoLc0YvbLXCzk7_u5qkCSweynzjGqeWqqhTwW/s1600/format2.png" height="22" width="640" /></a></div>
<br />
<h4>
But there is a catch, and a 20 year old two pixel bug:</h4>
<br />
<span style="color: red;">However there seems to be a bug in the way Photoalbums are managed:</span><br />
<span style="color: red;">Whenever there are more than 1 pictures in a given album, a picture's data section length is actually 2 bytes shorter than what it should be.</span><br />
<span style="color: red;">Reading the full length would make you read the picture comment length and first char as the last pixels data.</span><br />
<span style="color: red;">Therefore the last 2 pixels of each picture are bound to be corrupted.</span><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiOOHTFUBKgZMP7epUOOxEOssQPWQ0Rfriw2PY3QM0YBD6B8ag4BC5JLLa69j4F3tEy55HgMDkD4xmxXCY3aRT-7TAFx29ygl9AcNZspLj7N2edPcUUUXAvLQXHbiq1fqvQ4bfBCAaDmFZ/s1600/Bug.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiOOHTFUBKgZMP7epUOOxEOssQPWQ0Rfriw2PY3QM0YBD6B8ag4BC5JLLa69j4F3tEy55HgMDkD4xmxXCY3aRT-7TAFx29ygl9AcNZspLj7N2edPcUUUXAvLQXHbiq1fqvQ4bfBCAaDmFZ/s1600/Bug.PNG" height="320" width="282" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Last pixels of the picture are corrupted because the image comment size entry overlaps it.</td></tr>
</tbody></table>
<br />
I find it funny uncovering such a Two pixel bug 19 years after the game release!<br />
<br />
You developers thought nobody would ever notice uh ? Sorry about that ^^<br />
<br />
Noticing this subtle bug was impossible for even attentive players since pictures are slightly cropped in the Owner's kit: <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRQ9uICsToh7d10vClDCHbOX8Q4bBS-dkVOKMn4kY-dhI0fbblHJSt0ZsrUk0Aet6AqPkvVf4Mp0sMu_UEympz_CAghTu9G8T9v8NtvwZwAymvUDJjVP6vUeV56Cgc3K8_kody8mAPWrZ7/s1600/ok1.PNG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRQ9uICsToh7d10vClDCHbOX8Q4bBS-dkVOKMn4kY-dhI0fbblHJSt0ZsrUk0Aet6AqPkvVf4Mp0sMu_UEympz_CAghTu9G8T9v8NtvwZwAymvUDJjVP6vUeV56Cgc3K8_kody8mAPWrZ7/s1600/ok1.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">No visible bug in there, but the pic is cropped !</td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
While the raw pic contained in the photoalbum is slightly larger and decodes like this :<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqnn_5T7WqI-mYM5jc5vuFtlE5DfRAwDKRs5-clTT0mBMDXKoQDxZVzD557Ss3vEfs938A_DA6queuEnPGf828yTc4fe1l7foPpGfRQraVTEQ4gdYAmcH_0Ay4u2nOapbLg-hCZsilX68w/s1600/ok2.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqnn_5T7WqI-mYM5jc5vuFtlE5DfRAwDKRs5-clTT0mBMDXKoQDxZVzD557Ss3vEfs938A_DA6queuEnPGf828yTc4fe1l7foPpGfRQraVTEQ4gdYAmcH_0Ay4u2nOapbLg-hCZsilX68w/s1600/ok2.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Corrupted pixel in there !</td></tr>
</tbody></table>
<br />
Also, if you use the game "export pic as BMP" feature, you will notice the exported pic is corrupted in another way that doesn't show the bug :<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBtVP1_i9Jky_PYiKdZ2hOGkMX6V1l5eQSORlg7sQQyOnoqDBQgfRcJW-kTE4Uq9e9GWfbGh3kT_Su-JdPOrSMlFYZ1tAFHvSApLYbY0uIg6XK12Ti3HMUk9l9SayJiaNbDu_iga10mOx1/s1600/ok3.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBtVP1_i9Jky_PYiKdZ2hOGkMX6V1l5eQSORlg7sQQyOnoqDBQgfRcJW-kTE4Uq9e9GWfbGh3kT_Su-JdPOrSMlFYZ1tAFHvSApLYbY0uIg6XK12Ti3HMUk9l9SayJiaNbDu_iga10mOx1/s1600/ok3.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Exporting pic using the game features doesn't take the bug into account and the picture is slightly corrupted instead.</td></tr>
</tbody></table>
<br />
Unfortunately, this also means going back over the photo album ,adding, removing comments and moving around from inside the Owner's kit seems to be a dangerous activity that might corrupt the Album file.<br />
That's why I never usually use the commenting option.<br />
<br />
<h4>
Trying things out:</h4>
<h4>
</h4>
Okay, let's not give the (awesome) C1 developers to much hard time about that two decades old pair of sketchy pixels and do something constructive instead.<br />
<br />
We can now write a <a href="https://github.com/LoneShee/SLKExamples/blob/master/C1_Photoalbum2HTML.py">quick script </a>to confirm everything works as expected.<br />
What about generating a crude HTML gallery from the game folder using all photoalbums to check our findings ?<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSNTnIZcctzjGxeXZvxW-K9nO0bPKgRcpdXUR-VjhOhZyuVCbxqWG0I5hee2It9xH7AQLvX1hvvy2ljXZdYA44KSXZBG_toX6Smu2wKyJ2aOBfOSfqnsYV2MkSh1KPQ486rm2Q0MgHguxD/s1600/Gallery.PNG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSNTnIZcctzjGxeXZvxW-K9nO0bPKgRcpdXUR-VjhOhZyuVCbxqWG0I5hee2It9xH7AQLvX1hvvy2ljXZdYA44KSXZBG_toX6Smu2wKyJ2aOBfOSfqnsYV2MkSh1KPQ486rm2Q0MgHguxD/s1600/Gallery.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">There you have it, a quick HTML gallery of all of your Albian population with a quick glance.</td></tr>
</tbody></table>
<br />
I hope you learned some interesting things there.<br />
<br />
I promise that when I'm done with the most common game file formats we will get back to slightly more Norn oriented tutorials and explorations, but my goal is to give out as much information about the game as I can so other people can use it for their own needs.<br />
<br />
See you soon !<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td class="tr-caption" style="text-align: center;"><br /></td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-31768508441101924262014-12-13T00:31:00.001+01:002015-03-13T11:03:11.722+01:00Repairing and understanding the lost "dde: pict" command (Taking photos of C1 Norns)<br />
One promising nugget in the <a href="http://www.gamewaredevelopment.com/downloads/cdn/creatures_caos_guide.pdf">Creatures 1 CAOS reference</a>, is the "dde: pict" command.<br />
<br />
According to the documentation,<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUKg6EbYkeT_uUI9qZ5baMberzFyX5VGHZZaJPXnDx6yXPiqcXlN5DlXOItzTIZcG6b9q8zoBVIn9KRxmTGAqBYIN5hfaROzWyGzn3vIwZqVYcBEkaY7DD74X1jrmNc-OqxUnpmwkTbkUU/s1600/Doc.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUKg6EbYkeT_uUI9qZ5baMberzFyX5VGHZZaJPXnDx6yXPiqcXlN5DlXOItzTIZcG6b9q8zoBVIn9KRxmTGAqBYIN5hfaROzWyGzn3vIwZqVYcBEkaY7DD74X1jrmNc-OqxUnpmwkTbkUU/s1600/Doc.PNG" /></a></div>
<br />
Unfortunately, as many other things this command not only lacks critical bits of explanation but is also inherently broken (at least considering the above definition) and when used produces less than stellar results:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDdoUPxWguHi5BcKTXz4e1imtRqoxtBzL-fTS-VrZOpJZHoaPFQFRxJjU8Vl61rHQB3zHAZvEw5BUmiSgUc26TIOOMJXRdtGn1_heaP9lpqyhaLJVe7A8s2Lo0ows1LLb9ntCOuIaM1prs/s1600/err.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDdoUPxWguHi5BcKTXz4e1imtRqoxtBzL-fTS-VrZOpJZHoaPFQFRxJjU8Vl61rHQB3zHAZvEw5BUmiSgUc26TIOOMJXRdtGn1_heaP9lpqyhaLJVe7A8s2Lo0ows1LLb9ntCOuIaM1prs/s1600/err.PNG" height="235" width="400" /></a></div>
<br />
<br />
It's a shame we can't use this functionality in our own tools to take pictures as the Owner's kit does.<br />
Or can't we ?<br />
<br />
One of the main motives behind the site being uncovering such lost knowledge and abilities of the ancient Shee, come with me and find out how to understand and ultimately take advantage of this lost command.<br />
<br />
<a name='more'></a><br />
TL;DR: If you are not interested in the actual process of understanding how the command worked in the first place but just want to use it, jump to the very bottom of the page for a wrap up.<br />
<br />
So where do we start ?<br />
All further documentation being forever lost, and the Internet not providing any tutorial on that matter, we will once again have to resort to reverse engineering parts of the original game to find out how things work.<br />
<br />
The most obvious candidate for providing a sample of this command is the Owner's kit, since it does allow to take pictures of our creatures and exporting them to BMP's.<br />
<br />
So let's fire up our <a href="https://www.hex-rays.com/products/ida/support/download_freeware.shtml">favorite debugger</a> an load the owner's kit in there.<br />
<br />
One logical thing to look for would be searching the function attached to the "Take picture" button of the kit.<br />
But Creatures and all associated kits are written as MFC applications, and those use a slightly more complex mechanism to manage interface interactions that what you might be used to.<br />
We will deal with those mechanisms in more detail in a future post, for now let's find an easier way.<br />
<br />
Since we are looking for how "dde: pict" works, let's look for it in the application "Strings" window:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUxtPDMLeOUwon6ySWC_cwXmRfQGSttqOs7XLD2_2Oi3VXNNnN-20IOUEE9wHaVeoVLe2aqKjgXOoCCUxV4AtDfdslB_AO7V3n_VrhhGRPNe2ZYxlfTJf6oA8B2ysqiz-0nsSaX4v168AR/s1600/pict+string.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUxtPDMLeOUwon6ySWC_cwXmRfQGSttqOs7XLD2_2Oi3VXNNnN-20IOUEE9wHaVeoVLe2aqKjgXOoCCUxV4AtDfdslB_AO7V3n_VrhhGRPNe2ZYxlfTJf6oA8B2ysqiz-0nsSaX4v168AR/s1600/pict+string.PNG" height="169" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Here it is, among other CAOS commands !</td></tr>
</tbody></table>
<br />
Double clicking on the entry and following It's references, leads us to the place in the code where the command is actually used, and it looks something like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisW2bKqZqmhQz8MXdqjSHUVaTclUS-Z1T9r_7LFUrsVZeqz6jT4SKYak197X7912NKdtiN6XHSN98Cr-hxSftc_kx-olcTV4yLQta1OwgFIoX2NU9CAUBgF19S2C0PK4ocIbLCF_9E9McW/s1600/command+compo.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisW2bKqZqmhQz8MXdqjSHUVaTclUS-Z1T9r_7LFUrsVZeqz6jT4SKYak197X7912NKdtiN6XHSN98Cr-hxSftc_kx-olcTV4yLQta1OwgFIoX2NU9CAUBgF19S2C0PK4ocIbLCF_9E9McW/s1600/command+compo.PNG" height="320" width="248" /></a></div>
<br />
<br />
We can see that a series of calls is crafting the final command from well known pieces : " inst,dde: panc, dde: pict" and ",endm".<br />
<br />
But something seems to be happening between the "dde: pict" and ",endm" part.<br />
This is most likely some additional parameter, which absence would explain why the command failed when we first tried it:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj9MhS6Bqq9yHHWIb5Jpdx-jXv6PhsrDRr6v1ezvzeFq7DbbFmHkCsBi4p-BFyPRp1bOxnU96jRrXx0L35vLrQdXb9cGPK7-HocxihzIOLKouKfYrhGI0EVpt65XkPriSvouTj3SLEVlpr/s1600/composition.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj9MhS6Bqq9yHHWIb5Jpdx-jXv6PhsrDRr6v1ezvzeFq7DbbFmHkCsBi4p-BFyPRp1bOxnU96jRrXx0L35vLrQdXb9cGPK7-HocxihzIOLKouKfYrhGI0EVpt65XkPriSvouTj3SLEVlpr/s1600/composition.PNG" height="400" width="273" /></a></div>
<br />
<br />
It might not be obvious at first what this additional data is by reading dead listing.<br />
Let's rather just use the button, and try to intercept the final command right when it is used, shall we ?<br />
<br />
To do this, we need to set a breakpoint after we think the command will be completed, and run the game, take a picture, and hope we end up where we thought we would.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgh6g9DbgYU2zS0rh6WWg7IhP5vptfRj3NWL09P0vzGKqPv6NHlWOf_jmlulGcskq_OotTuVpHRuQ0alx0vwTMQBbcHFsBV0-yViQU88O9XNJkJ_tE6vqHKrbWts7ZJkjToNGtxcsvjMbz/s1600/bp.TIF" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgh6g9DbgYU2zS0rh6WWg7IhP5vptfRj3NWL09P0vzGKqPv6NHlWOf_jmlulGcskq_OotTuVpHRuQ0alx0vwTMQBbcHFsBV0-yViQU88O9XNJkJ_tE6vqHKrbWts7ZJkjToNGtxcsvjMbz/s1600/bp.TIF" height="320" width="202" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Let's add the breakpoint after the command is crafted, but before the first "call" follwing it so nothing has the opportunity to break the chain we're looking for.</td></tr>
</tbody></table>
<br />
<br />
Before performing our stunt we will also need to slightly tweak the interface.<br />
When ran, the Creatures 1 exectuables adopt the old style 8+3 naming scheme instead of the more modern full format we're used to.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAFaFhOWlBEzgPMMFoeVGsOkEksul63-ShfZ7V2-ENnMY0vhwIbUynlFaxNQTDGTIYxmB3skza7jZSCWaG9BV6abr6sfxapGEmbRuXE22GJJmvlEpal1WnXanyR_7wR3l7b91XBNYSuFRl/s1600/short.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAFaFhOWlBEzgPMMFoeVGsOkEksul63-ShfZ7V2-ENnMY0vhwIbUynlFaxNQTDGTIYxmB3skza7jZSCWaG9BV6abr6sfxapGEmbRuXE22GJJmvlEpal1WnXanyR_7wR3l7b91XBNYSuFRl/s1600/short.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Owner kit process name is limited to 8+3 chars</td></tr>
</tbody></table>
<br />
Going to the "Debugger->Process Options" menu, allows us to change the target process we will be looking for:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgybcBbTiiViJhF4rtYwkXu12W4FGOSOjbxOVKsQyqvdwRH8_iG-vO4nCEO7tVgMSYAYY0aLbvy7oBZDpRdxnDySq9pKPZ6BjOZLFD8hYddeEGZwcN1hIs8q1fvc8EvBmJZKz0QTF4ZMj9Q/s1600/Tuning1.TIF" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgybcBbTiiViJhF4rtYwkXu12W4FGOSOjbxOVKsQyqvdwRH8_iG-vO4nCEO7tVgMSYAYY0aLbvy7oBZDpRdxnDySq9pKPZ6BjOZLFD8hYddeEGZwcN1hIs8q1fvc8EvBmJZKz0QTF4ZMj9Q/s1600/Tuning1.TIF" height="260" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This needs to be changed....</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLQ1OS_T1ez4krBNEvxu03sD14mUfWpDpo2HqpO4KThM4JpKnSG0QyjBIwCItxJP5F4GjJfj4aghAU27WRllvnF8Jy9aIPu_Ddc0F19zbt4sPBf13R6xtLXB83PfmrKeUy4KkFNV5kpMYw/s1600/tuning+2.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLQ1OS_T1ez4krBNEvxu03sD14mUfWpDpo2HqpO4KThM4JpKnSG0QyjBIwCItxJP5F4GjJfj4aghAU27WRllvnF8Jy9aIPu_Ddc0F19zbt4sPBf13R6xtLXB83PfmrKeUy4KkFNV5kpMYw/s1600/tuning+2.PNG" height="260" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">...to this.</td></tr>
</tbody></table>
<br />
With this done, let's fire up the game, run the Owner's kit, and pick the "Debugger->Attach to process" option, and proceed to take a pic.The debugger should step in at this point and land us where we expected:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig9IHFOT3rMzJctLbX8b__a1CQ6pMj5WSGpA53-5aYELlbQFuR-dPcPZezGCp8LhBhVpsiLwFBxqVdxZ0IiZ98x6YUsM379QdiAAmxJix3CYJawWGI70sHz2DdKOpCERCI3KcISlC51yGo/s1600/Break.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig9IHFOT3rMzJctLbX8b__a1CQ6pMj5WSGpA53-5aYELlbQFuR-dPcPZezGCp8LhBhVpsiLwFBxqVdxZ0IiZ98x6YUsM379QdiAAmxJix3CYJawWGI70sHz2DdKOpCERCI3KcISlC51yGo/s1600/Break.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">That's it !</td></tr>
</tbody></table>
From there, we can just access the current function stack, and see our beautiful command ready to be run on the right side.<br />
<br />
A quick right click over the memory chunk allows us to "stringify" it for easier reading:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_Ubrjv1mYswSs1koLLObe27p2KDhjK6aGuzq5XcUfdNL7kslwDpRvHLd-957pbJaOIFeBbenj3ri8xaua-qrhnOQ_ykKeVouz67Ibk1q4mOT7K3ZBtJE8ZIrGv3F6K5Y6UBmrhBIglD65/s1600/stringify.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_Ubrjv1mYswSs1koLLObe27p2KDhjK6aGuzq5XcUfdNL7kslwDpRvHLd-957pbJaOIFeBbenj3ri8xaua-qrhnOQ_ykKeVouz67Ibk1q4mOT7K3ZBtJE8ZIrGv3F6K5Y6UBmrhBIglD65/s1600/stringify.PNG" height="464" width="640" /></a></div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgad766RwQwa6DS7Azpq_ZxMxUfx-0L8MDTG_ojxK-1RNDZpmjkcseCwOACQ56BUrhLDhUzELPR41soJuKCJU-FJKeBt6asJPOb-8z3VbTGNCAxQS-Cr4ROaCb93g9I7l7KUrdfybeVq-nL/s1600/readable.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgad766RwQwa6DS7Azpq_ZxMxUfx-0L8MDTG_ojxK-1RNDZpmjkcseCwOACQ56BUrhLDhUzELPR41soJuKCJU-FJKeBt6asJPOb-8z3VbTGNCAxQS-Cr4ROaCb93g9I7l7KUrdfybeVq-nL/s1600/readable.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">More readable isn't it ?</td></tr>
</tbody></table>
<br />
So this is the final command the applet runs ?<br />
Letting the debugger resume the Owner's kit process results in what we're used to, and the creature pic is taken.<br />
<br />
Then what is that "x|î" mess in there?<br />
This doesn't look like anything we're used to when programming CAOS.<br />
<br />
Most CAOS mnemonics, instructions or variables are 4 characters long, so this probably isn't even an internal game pointer or token of any kind.<br />
Also it's barely printable characters where we are used to human readable keywords. <br />
Does this weird command even work ?<br />
Pumping it into a CAOS console gives us the answer:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHBRcVtCiuWQ_LhuGxr0XQ91CTkndFCRrOVQ4xcIZma_IOYnI5kiGqBLpg3rn1CIx84S9nmzI9ZVhcIGhY8BXKICAjT5wLLw2z0-AcXO-fuyOBO-0ubutti45Rws3P2Ly8ztwNr5HcEUVQ/s1600/dde.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHBRcVtCiuWQ_LhuGxr0XQ91CTkndFCRrOVQ4xcIZma_IOYnI5kiGqBLpg3rn1CIx84S9nmzI9ZVhcIGhY8BXKICAjT5wLLw2z0-AcXO-fuyOBO-0ubutti45Rws3P2Ly8ztwNr5HcEUVQ/s1600/dde.PNG" height="192" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Seems to work !</td></tr>
</tbody></table>
<br />
Soooo, this seems to work (well, at least it didn't kill the game this time :)<br />
, and at this point , we uncovered some significant pieces of information:<br />
<ul>
<li>Contrary to what the documentation says, the command requires an additional parameter</li>
<li>Those parameters seem to be raw values, and not their readable representation. </li>
<li>The returned picture seems to be a .spr file rather than a BMP as was expected.</li>
</ul>
Let's have a look at this "temp.spr" file, <a href="http://sheeslostknowledge.blogspot.fr/2014/11/parsing-creatures-1-spr-files.html">understanding it should pose no problems</a> now.<br />
The file is stored in the game root directory:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUbqPgqH7-0cdHCwkC15Al1AGdMmRduuO8Q_jGgHqUf0ypsj34VqpgaZfMczD614WIrgMiCzotLjj_KYR-_VluLOAT0gfkpwDFbK9Ti5GTjpsty_HMBamZPd9AYXV8wxmvvabQXSztGDUC/s1600/tmpspr.TIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUbqPgqH7-0cdHCwkC15Al1AGdMmRduuO8Q_jGgHqUf0ypsj34VqpgaZfMczD614WIrgMiCzotLjj_KYR-_VluLOAT0gfkpwDFbK9Ti5GTjpsty_HMBamZPd9AYXV8wxmvvabQXSztGDUC/s1600/tmpspr.TIF" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXlvovfduBqu_TZYV5Qeb_hDiUpUFUWmiFMTI486C3u3MeMqav68WzqCqfsnu0Aa4da0Yd6Q6-XV7WQebGPz-ui98ua93cyJ7P61cCgfF_CVKdVEaYpnh7OeCkk5t9PoiUE_zdwHImhXKP/s1600/tempsprhex.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXlvovfduBqu_TZYV5Qeb_hDiUpUFUWmiFMTI486C3u3MeMqav68WzqCqfsnu0Aa4da0Yd6Q6-XV7WQebGPz-ui98ua93cyJ7P61cCgfF_CVKdVEaYpnh7OeCkk5t9PoiUE_zdwHImhXKP/s1600/tempsprhex.PNG" /></a></div>
<br />
Well, unfortunately this doesn't fit our earlier understanding of the .spr file format and doesn't seem to be a valid.spr file...<br />
<br />
But like our favorite small furry and stubborn Norns, we won't let such small details prevent us from doing what we want to.<br />
At this point it's <a href="http://sheeslostknowledge.blogspot.fr/2014/01/getting-c2-chemicals-descriptions.html">just another</a> round of <a href="http://sheeslostknowledge.blogspot.fr/2014/01/reversing-and-parsing-c2.html">file format reversing</a>, so let's get this done!<br />
<br />
This one looks scary, a huge blob of raw data with no apparent headers or readable strings.<br />
But it's simpler than it looks.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVfHWziY-de3GWRUZd4ajpxtOoEVmTyglkh73tfVln30SNXACy3t6V1vjMJkQL89TwEHdSuoAf2Cet25TPMHYKOPsm0PEmIMO2MECBQbbkn_goxN1to3vfhI1cEUOQ9GjlEh7SJVmeKRlh/s1600/sprid.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVfHWziY-de3GWRUZd4ajpxtOoEVmTyglkh73tfVln30SNXACy3t6V1vjMJkQL89TwEHdSuoAf2Cet25TPMHYKOPsm0PEmIMO2MECBQbbkn_goxN1to3vfhI1cEUOQ9GjlEh7SJVmeKRlh/s1600/sprid.PNG" /></a></div>
<br />
Let's have a look at the three first groups of bytes.<br />
Those stand out as they seem to be 4byte wide and 00 padded contrary to the rest of the file.<br />
It might not seem obvious at first but what if we converted them to ASCII characters ?<br />
(Yes intuition DOES play a major role in reversing), this gives us :<br />
<ul>
<li>0x78 = "x" = 120</li>
<li>0xEE = "î" = 238</li>
</ul>
Does it seem familiar ? those are two of the weird characters we had to append the command before running it.<br />
Are they really ? Could they represent an image height and width?<br />
<br />
Lets answer both questions by running the command again, but this time using "ABC" as the parameter:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHloGabI9b03tBeCFzl1q2a08FDdm1WVcKAq3cwXa93nJw2CA0rbbGmPQOr0ZXyVW7a1zxehJHscvO1eEnaHwEaCE5YHWovYXFsisMY9GwryRyIyodv1XZjwUHIgOZvuP2icO_DsjDBLnL/s1600/ABC.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHloGabI9b03tBeCFzl1q2a08FDdm1WVcKAq3cwXa93nJw2CA0rbbGmPQOr0ZXyVW7a1zxehJHscvO1eEnaHwEaCE5YHWovYXFsisMY9GwryRyIyodv1XZjwUHIgOZvuP2icO_DsjDBLnL/s1600/ABC.PNG" height="206" width="400" /></a></div>
<br />
Good, the game doesn't seem to complain, and the tmp.spr file seems much bigger than earlier ( A=0x41, B=0x42,C=0x43 , and all are higher than the value of a small "x". It's then logical they would result in a bigger file if they are used to specify the picture geometry)<br />
<br />
What do we get inside the file itself?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrN6tuIQwpV173QxlVh3Uvoki3IGbEe2htTb7IiYi-LC2C9P49eOLptiAArSQ4dTqWfDAMmMsyCGMLOCmNPxDd6BloGAQ0GevKMTbmJ8tcToRWXopyyjAmCbKQGYYw9kvPvbfCvnlz5zCr/s1600/close.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrN6tuIQwpV173QxlVh3Uvoki3IGbEe2htTb7IiYi-LC2C9P49eOLptiAArSQ4dTqWfDAMmMsyCGMLOCmNPxDd6BloGAQ0GevKMTbmJ8tcToRWXopyyjAmCbKQGYYw9kvPvbfCvnlz5zCr/s1600/close.PNG" /> </a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Hmmm... not Precisely the values we were looking for, but those are pretty close and varied as expected towards specified values.<br />
Maybe the games takes some initiatives with the actual values ? Maybe it tries to round them to some practical boundaries?<br />
<br />
Let's assume it does and our values are indeed what we think, and try to make a valid .spr file out of this mess by manually appending <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIfa07geVfmjdfYlQ_qrzsamIGGjl_5HIVUai6OhHOXM4iTIfP0LTAsWxbUMpzvUFJeDAt3IXdnvRQ5EtGG6sh0rGHrFNprpucDZ3lRc6cZESSON6wljSWqnAb2zjd4iuSkGzpSVPhkIhq/s1600/Format.png">a valid .spr header</a> to the file, before that big blob of unknown data (we will be working on the original .spr file with the"x|î" values).<br />
It might also be a good time to realize that if we select the whole blob of unknown data that looks like raw image data (yes it DOES !), it's total size is 0x41A0, which happens to be equal to the product of two of the first parameters, further confirming our guess that two of the 3 first values of the file might be width and height information.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6EhxCTYK3-_rMSa25FSwF6fdHpVfHwXCmSuG5eYV5S7Ussy-1TvB0uJHy91KGRmqOP18477klgOVvQ4t1LvndbCtDmpuDLgiuPStUnS6CABIQ93Cl7sveMyDWav4UDq76MC-oTVdZewjt/s1600/size.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6EhxCTYK3-_rMSa25FSwF6fdHpVfHwXCmSuG5eYV5S7Ussy-1TvB0uJHy91KGRmqOP18477klgOVvQ4t1LvndbCtDmpuDLgiuPStUnS6CABIQ93Cl7sveMyDWav4UDq76MC-oTVdZewjt/s1600/size.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">0x78 * 0x8c = 0x41A0</td></tr>
</tbody></table>
<br />
Let's try to parse the reconstructed .spr file based on those assumptions :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEz2BPPs50cTm3vri9q141csmrhtiimErNsKGumVhZcrYpzgqpWd1y1Bcp8BD6MEjiyFlTM1hKMVXKZSkNj5cWruO_s0qjUXMaDUOl8OwS8MC-xWjnJX0hgilAPv9I7p0QRvLekTlKUQjx/s1600/pic.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEz2BPPs50cTm3vri9q141csmrhtiimErNsKGumVhZcrYpzgqpWd1y1Bcp8BD6MEjiyFlTM1hKMVXKZSkNj5cWruO_s0qjUXMaDUOl8OwS8MC-xWjnJX0hgilAPv9I7p0QRvLekTlKUQjx/s1600/pic.PNG" /></a></div>
<br />
<br />
Looks good to me !<br />
We rebuilt a valid header for the file and parsed it using our previously written image manipulation tools.<br />
The picture being upside down is only a minor inconvenience at this point, and we can be glad we recovered the expected picture from that seemingly invalid .spr file :)<br />
<br />
So what did we learn so far ?<br />
<ul>
<li>The "dde: pict" command expects a parameter</li>
<li>The parameter is not a readable string, but rather a series of 3 raw bytes.</li>
<li>Two of those bytes seem to represent the wanted snapshot width and height.</li>
<li>Running the command produces a temp.spr file that does not conform to the game .spr file format, but does contain enough information to produce a valid one.</li>
<li>I'll spare you the details, but further exploration shows that in actual game usage this temp file is then read by the Owner's kit, and appended to the creatures photo album stored in a file named something like "4b524630.Photo Album" which we will soon learn to parse too :)</li>
</ul>
Let's write a quick script to automate the process of taking and displaying a picture so we can play with the remaining mystery value to try to understand it's meaning<br />
<br />
You can get it <a href="https://github.com/LoneShee/SLKExamples/blob/master/C1_Takephoto.py">here</a>. <br />
<br />
By using this script, we can play a bit with the 3 parameters we can pass to the the "dde: pict" command by varying them and observing results.<br />
<br />
The outcome is that for the command being "dde: pict ABC":<br />
<ul>
<li>A is the image Width, between 1 and 255</li>
<li>C is the image Height ,between 1 and 255 </li>
<li>B didn't make any noticeable difference in the output image when varying it for any value between 1 and 255.I'm a bit ashamed to admit that it took me so long to realize that B is actually just supposed to be " | " which is the commonly used field separator for creatures commands (Yeah talk about intuition...), but that it's actual value doesn't seem to be checked. </li>
</ul>
<br />
There we have it, having understood and documented an useful and long lost command that will allow us to automatically take pictures of our favorite Norns, in arbitrary sizes up to 255*255 and save them in any common file format.<br />
Also by replacing the "camt" CAOS command by an arbitrary camera positioning command before taking the pic, we could take pictures of just any part of the world we might be interested in.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyHrMm8kbPNZdc1_zSqtDjBHgHHmxhQi_hyphenhyphenXm21PEyhN2zoUHbuy8r4HSaB-dpKzFULgh9np0bgIXSjZAaSyTwK8-Jgk4JeJ9SjJ8ayXHMv7ZHcUC968bW7VZc14Nrf0DwKP90oTx_BcaE/s1600/final.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyHrMm8kbPNZdc1_zSqtDjBHgHHmxhQi_hyphenhyphenXm21PEyhN2zoUHbuy8r4HSaB-dpKzFULgh9np0bgIXSjZAaSyTwK8-Jgk4JeJ9SjJ8ayXHMv7ZHcUC968bW7VZc14Nrf0DwKP90oTx_BcaE/s1600/final.PNG" height="316" width="400" /></a></div>
<br />
<br />
And while we're at it, why not take the opportunity to study the format of files holding the creatures photo albums?<br />
That will be the subject of our next article.But don't worry, it will be much shorter and slightly less technical.<br />
<br />
Meanwhile maybe you'd find the following wrap up useful as a reference:<br />
<br />
<br />
<h4>
dde: pict usage:</h4>
<br />
First you need to move the camera to the place where the picture is to be taken.<br />
The<span style="font-family: "Courier New",Courier,monospace;"> "dde: panc"</span> command is used to center the game window on current Norn, but you can use any other camera movement command instead to take pictures of other elements if you wish. <br />
<br />
Then you must issue the pict command.<br />
It's format is :<br />
<br />
"<span style="font-family: "Courier New",Courier,monospace;">dde: pict W|H" </span><br />
<br />
Where W and H are the raw values for expected picture width and height.<br />
(Remember not to use a human readable numerical representation but raw values here.)<br />
<br />
For example, if you want your pic 100x80 :<br />
<ul>
<li>chr(100)= "d"</li>
<li>chr(80)= "P" </li>
</ul>
the command would be :<br />
"<span style="font-family: "Courier New",Courier,monospace;">dde: pict d|P"</span><br />
<br />
The command returns the filename under which the pic was saved.<br />
It happens to always be "temp.spr".<br />
<br />
This file isn't a standard game .spr file.<br />
It's format is:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJzmRIeUsfC88tVrDe_54Q_PUk7QCmPwR3xQ-XcrObR0xT0deq0u8sw_KwtC8znKRT8QarZq8Pe_9s0ZJRJ194fnuJp5a6rhpcsBT8w0HZUfNVq5slPmuH3usUI7Zy4BMpMRo9PFs-8dz7/s1600/fake+spr+format.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJzmRIeUsfC88tVrDe_54Q_PUk7QCmPwR3xQ-XcrObR0xT0deq0u8sw_KwtC8znKRT8QarZq8Pe_9s0ZJRJ194fnuJp5a6rhpcsBT8w0HZUfNVq5slPmuH3usUI7Zy4BMpMRo9PFs-8dz7/s1600/fake+spr+format.PNG" height="41" width="640" /></a></div>
<br />
So you need to read out it's width and height from the file, read the data chunk, and use those to compose a viewable image.(how to do that has already been covered in <a href="http://sheeslostknowledge.blogspot.fr/2014/11/parsing-creatures-1-spr-files.html">the .spr file format article</a>)The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com1tag:blogger.com,1999:blog-1790862754650770452.post-24917678089681851242014-11-30T18:10:00.000+01:002014-12-18T00:05:38.598+01:00Reversing the C1 .exp file format part 1 (General layout and extracting the genome)It's been all those years, and despite a lot of talented persons having contributed to making Creatures tools or <a href="http://double.co.nz/creatures/developerinformation.htm">documenting the game various features,</a> there still isn't any available description of the .exp file formant anywhere as we're nearing 2015.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT9wNioBthZuf-2PDGZXfH-k5AH_7VgGtaJCHnhtVVtU_3I_rt5hI4O1Bp27HS3Gh27aMnZ3vUtXyp2L-vcWV4CebvPegZsPnzPso1NMcvGmWg9w6sl9tK2OWAzeMpmZfLX8hzhId5NFwf/s1600/Intro.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT9wNioBthZuf-2PDGZXfH-k5AH_7VgGtaJCHnhtVVtU_3I_rt5hI4O1Bp27HS3Gh27aMnZ3vUtXyp2L-vcWV4CebvPegZsPnzPso1NMcvGmWg9w6sl9tK2OWAzeMpmZfLX8hzhId5NFwf/s1600/Intro.PNG" /></a></div>
<br />
<br />
The .exp files are the format in which creatures are exported or imported from and to the game.<br />
<br />
Obviously, they contain about anything one could need to know about a given Norn, and exploiting them for writing custom tools might allow for a lot of interesting options such as exporting a critically ill norn, performing offline surgery on the file, and reimporting it into the game.<br />
<br />
This would allow curing a couple otherwise fatal issues since the ingame mechanics don't provide any means of removing a given chemical from a creature bloodstream or reinvigorating degraded C2 organs.<br />
(See the case of <a href="http://sheeslostknowledge.blogspot.fr/2014/01/investigating-effects-of-cyanide.html">C2 grendels being oversensitive to cyanide poisoning</a> because they lack the chemical reaction genes that would allow them to lower their cyanide levels)<br />
<br />
In this series of articles, I will describe the process of reverse engineering the C1 (and later C2) .exp file format so any programmer out there can use the information to implement .exp file manipulating programs.<br />
<br />
The first articles of the series will show the process followed so more people can learn "how it's done" and maybe later take on reversing other undocumented game file formats.<br />
Hopefully, if enough information can be gathered about the format, a final article will sum everything up into the cleanest and most complete description possible.<br />
<br />
For this first article, we will analyse the general file layout, and learn how to extract a working genome file from an .exp file.<br />
<br />
Let's dive into binary DNA !<br />
<br />
<a name='more'></a><br />
<h4>
What do we expect to find ?</h4>
Before diving head first into binary data, it might be useful to list what we're expecting to find in an exp file.<br />
This might allow us to make sense of bigger chunks of data by recognizing already known patterns. <br />
<br />
Think about it.<br />
When you export a Norn from a given game and then re-import it in another place, what information needs to be carried around ? <br />
<br />
- The first and most obvious part is that generic Norn info must be there: it's moniker, name, owner information, genetic code,filiation...<br />
- A snapshot of the norn Internal state must also be kept (otherwise an imported Norn would have an empty chemical system, and instantly die of a lack of glycogen)<br />
- Same goes with the brain, it's state must be saved somehow, along with all the Norn's experience, and learned words.<br />
- Sprite data? This is unlikely. Think of the case of the purple mountain Norns.<br />
They come as a full blown installer, and not as .exp files.<br />
If you import a PMN into a virgin C1 game from a .exp file , it will not show the expected appearance but that of the default brown norn.This suggests that sprite and .att data is an external resource not included in the .exp.<br />
(After all you have to distribute .spr and .att files when you design a new breed don't you ?)<br />
- The Norns life stage, age...<br />
-Pregnancy state is probably saved somewhere too (probably along with the baby genome) as exporting a pregnant Norn and reimporting it seems to remember if the Norn was pregnant.<br />
-The photo album however does'nt seem to be stored in the Norn's .exp file as it size doesn't increase with the number of taken pictures.<br />
<br />
<h4>
The overall file layout</h4>
If we just open the .exp file in a hexadecimal editor, and randomly browse through it in search for meaningful information, there are a couple of things that pop out.<br />
<br />
We can find a few human readable things or stuff that looks familiar:<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4lMmKeJ65jyB6DuFjiedFlVZNXsoQntZZY3PXgskaKOVCvD0aDij_A6K-MS44N3RQPiSSzWEjmwZZBI6zuv-NN41tYQ1V2BGkWbsG8S9vKYRq8rJFWp7YYEjA4ecA9JCrg9rOF1jNCP_s/s1600/monker.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4lMmKeJ65jyB6DuFjiedFlVZNXsoQntZZY3PXgskaKOVCvD0aDij_A6K-MS44N3RQPiSSzWEjmwZZBI6zuv-NN41tYQ1V2BGkWbsG8S9vKYRq8rJFWp7YYEjA4ecA9JCrg9rOF1jNCP_s/s1600/monker.PNG" height="94" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><u>A creature moniker</u></td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv_Z-HLMYBsUXUYCNbnvMdkYPphFA-8-9kH23Mcd4zuQTBP00Lk5jlguBD4srCWiINhuvBcKalIzltQ8H152zSgs47ZXCDYN9GSxQbZw18qXf-bE8TcXjpyyrYKH4zRz7FGUWrVHy2DTTg/s1600/vocab.PNG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv_Z-HLMYBsUXUYCNbnvMdkYPphFA-8-9kH23Mcd4zuQTBP00Lk5jlguBD4srCWiINhuvBcKalIzltQ8H152zSgs47ZXCDYN9GSxQbZw18qXf-bE8TcXjpyyrYKH4zRz7FGUWrVHy2DTTg/s1600/vocab.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Looks like vocabulary status</td></tr>
</tbody></table>
<div style="text-align: center;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2kAmEcGnE_xeHNHf4XcvQgNdriphe4xACiZ04WOlkOxZdCXTawIqo3SL3Atpoyc6FhXquUg1ecssGhe82uCfLzyw1cVERWq7jcgRSFC56jwxsqiiYg9i9yFGGqHmrQQojeZNsDb22_e_n/s1600/pos+genes.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2kAmEcGnE_xeHNHf4XcvQgNdriphe4xACiZ04WOlkOxZdCXTawIqo3SL3Atpoyc6FhXquUg1ecssGhe82uCfLzyw1cVERWq7jcgRSFC56jwxsqiiYg9i9yFGGqHmrQQojeZNsDb22_e_n/s1600/pos+genes.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This section looks like the pose genes one in gen files but lacks the genes structure</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx67hhXU5m1wWAcE4nW19Ph92-jCS62z50tmxfTRW3aINJoFSV3yq4LQcigsIz4URPl-YKz4aBtI65RflqdlHrHPjn6TwLa-0DefdRjzCS1yBnGoUPLQgLDOTPP1jzfjnqERjULfedmELE/s1600/Genes.PNG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx67hhXU5m1wWAcE4nW19Ph92-jCS62z50tmxfTRW3aINJoFSV3yq4LQcigsIz4URPl-YKz4aBtI65RflqdlHrHPjn6TwLa-0DefdRjzCS1yBnGoUPLQgLDOTPP1jzfjnqERjULfedmELE/s1600/Genes.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A huge blob of "gene" markers along with data, reminiscent of the .gen file format.</td></tr>
</tbody></table>
<div style="text-align: center;">
<br /></div>
<div style="text-align: left;">
One easy early step in reversing any file format is looking for readable strings.</div>
<div style="text-align: left;">
If we automate the process, along with the above information, we find a couple promising strings:</div>
<div style="text-align: left;">
"CGallery", "CBrain", "CBiochemistry" and "CGenome". Those really do look like markers defining sections inside the file.They also seem to provide us with important insight as to what might be the following data.</div>
<div style="text-align: left;">
Great! From on now, we will assume that a .exp file is made up of 5 sections delimited by those markers, and will be considering each section individually.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
(We know from previously gained knowledge of Creatures internals that few file formats contain lookup tables that would allow reading of only interesting sections, and that raw complete reading of a file is often the only method to parse it.It then makes sense that if the .exp file is an aggregate of other file formats/data structures, markers might be needed to differentiate between chunks of data for which no previsible length can be guessed prior to parsing.)</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
From on now we will call the various sections as such:</div>
<div style="text-align: left;">
<u>Section 0:</u> The Header of the file, the few bytes before the first "Cgallery" marker</div>
<div style="text-align: left;">
<u>Section 1:</u> The CGallery section containing everything between the "CGallery" and "CBrain" markers</div>
<div style="text-align: left;">
<u>Section 2: </u>The "CBrain" section, containing everything between the "CBrain" and the "CBiochemistry" markers</div>
<div style="text-align: left;">
<u>Section 3:</u> The "CBiochemistry" section,containing everything between the "CBiochemistry" and the "CGenome" markers<u> </u></div>
<div style="text-align: left;">
<u>Section 4: </u>The "CGenome" section containing everything between the "CGenome" marker and the end of the file.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
You can use the <a href="https://github.com/LoneShee/SLKExamples/blob/master/C1_exp_file_splitter.py">following python script</a> to split an .exp file into those chunks for easier manipulation.</div>
<div style="text-align: left;">
<br />
<br /></div>
<h4 style="text-align: left;">
Making sense of Section 4: the "CGenome" section.</h4>
<h4 style="text-align: left;">
</h4>
<div style="text-align: left;">
Let's start with an easy one.</div>
<div style="text-align: left;">
If we look at where the "CGenome" string is, we can see that what follows strongly resembles a .gen file format:</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihnXeip62ojShLC2_dEZGhKGm9-T467NnzijpD67kH5068ccVPV7S5ihPynMidWzvBM_lAE8sq3GANEx62-n37qs8JroA8ZfKzwf_93xNUMKHXlzpG-DF0-NzhHjBLpZ0bJqhVD_oPgDhp/s1600/Genome.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihnXeip62ojShLC2_dEZGhKGm9-T467NnzijpD67kH5068ccVPV7S5ihPynMidWzvBM_lAE8sq3GANEx62-n37qs8JroA8ZfKzwf_93xNUMKHXlzpG-DF0-NzhHjBLpZ0bJqhVD_oPgDhp/s1600/Genome.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The .exp file centered on the "CGenome" marker</td></tr>
</tbody></table>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Let's compare it with the corresponding .gen file for this creature:</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBmKTRVJN2XHOF8YXKXI1I8B0xWFHkOSzny26NFhSbFtkmViznCB0ryrVOwGflwIwZ7i1hOAIp1KSIZ9xzlCBYWv0Hg3pycP0-VtLVG3lO6f4NY-zKUI9DgQCLhnu0P-ULOyXzb312oSdb/s1600/expgenome.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBmKTRVJN2XHOF8YXKXI1I8B0xWFHkOSzny26NFhSbFtkmViznCB0ryrVOwGflwIwZ7i1hOAIp1KSIZ9xzlCBYWv0Hg3pycP0-VtLVG3lO6f4NY-zKUI9DgQCLhnu0P-ULOyXzb312oSdb/s1600/expgenome.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Above, the .exp file, below, the .gen file for the same creature</td></tr>
</tbody></table>
<div style="text-align: left;">
We've got a perfect match !</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
It seems that this section of the file is made of a 22 byte header, and then followed by a valid .gen file.</div>
<div style="text-align: left;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx3uuxH-m-A_-J7b-wFHwDx_SakTCWXDt-pgfV-rEHuf5_AjxNq5d1FVDpxcH_kiMAd2YOr_Q_PJX5BdViE3ZUE1d5GFVGcqfQkff55qLfPeiJPbp0ZkKEg2zqxDAHrCrsRpIqFYhoHpc7/s1600/Genome+header.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx3uuxH-m-A_-J7b-wFHwDx_SakTCWXDt-pgfV-rEHuf5_AjxNq5d1FVDpxcH_kiMAd2YOr_Q_PJX5BdViE3ZUE1d5GFVGcqfQkff55qLfPeiJPbp0ZkKEg2zqxDAHrCrsRpIqFYhoHpc7/s1600/Genome+header.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The 22byte header preceding the .gen file in the "CGenome" section</td></tr>
</tbody></table>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
If we measure the section beginning at the "gene" marker and ending at the end of the file, we've got a perfect 20 001 bytes(~20ko), which is the exact size of .gen files.</div>
<div style="text-align: left;">
<br />
Hooray, we can now extract this part of the file, save it to a .gen file and import it into a Genkit to confirm that it is valid.(Indeed, it is also strictly similar to the "1UGB.gen" file for this Norn found in the Genetics directory. That's one huge chunk out of the way!</div>
<div style="text-align: left;">
<br /></div>
<h4 style="text-align: left;">
</h4>
<h4 style="text-align: left;">
Making sense of the remaining "CGenome" header:</h4>
<div style="text-align: left;">
<br />
So let's try to decode the 22 remaining bytes so we can wrap up our understanding of section 4.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
-We can see that the "CGenome" string is preceded by a 2 byte value reading "7". </div>
<div style="text-align: left;">
7 is the length of "CGenome" string and we already know from our previous reverse engineering musings that this is the "CSTRING" format in which many strings are stored inside the game files( those strings are composed of a 1 or 2 word prefix specifying length, and then the corresponding string).</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
-We can also easily identify the string "1UGB" which is the Norn's Moniker. </div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
That leaves us with only 9 unknown bytes to make sense of:</div>
<div style="text-align: left;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmzZvecOOKHlOAaHpcr-dEyUD_prVTr1_zMwIoos8jS7Kiy15gW6pviXwPTnj9zCYACDfXUkmn0LAAr_BrLIi0b0fEoBrcU6zq8dPAmbPcGdaUvfkgGYZphA2OlkKiXPh9aPAD4A_D02Gy/s1600/Header+breakout.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmzZvecOOKHlOAaHpcr-dEyUD_prVTr1_zMwIoos8jS7Kiy15gW6pviXwPTnj9zCYACDfXUkmn0LAAr_BrLIi0b0fEoBrcU6zq8dPAmbPcGdaUvfkgGYZphA2OlkKiXPh9aPAD4A_D02Gy/s1600/Header+breakout.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Colorized version of the "CGenome" section with explanation</td></tr>
</tbody></table>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
What is that "214e" right after the "CGenome" marker ?</div>
<div style="text-align: left;">
Well, translating this hexadecimal value to decimal gives us "20001" sounds familiar ?</div>
<div style="text-align: left;">
Yes, this is the exact length of the .gen file data we found out just earlier and stored later in this section.</div>
<div style="text-align: left;">
(Just remember that a multiple byte value might be stored in reverse order in files, here "214e" really means "4e21" )</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYI9Anlg9nmlhuixvIvJHtgQqgA5lzahNk8Vnv8QKokr5kCIkPK2SfHLzr3wkbc5qBeZdCyMV2RHsvpl5-90UFqHwxbfOZIA1ahMgKl_BJI4KEpvWfrCmzqHHMfPpK3AFdr-_KKivV4XR0/s1600/214e+length.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYI9Anlg9nmlhuixvIvJHtgQqgA5lzahNk8Vnv8QKokr5kCIkPK2SfHLzr3wkbc5qBeZdCyMV2RHsvpl5-90UFqHwxbfOZIA1ahMgKl_BJI4KEpvWfrCmzqHHMfPpK3AFdr-_KKivV4XR0/s1600/214e+length.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Length of the .gen seciton selected in a hex editor is shown to be 4e21</td></tr>
</tbody></table>
<div style="text-align: left;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh68iAAnQ2FguCqNHgbneHV-0c9NdMtgoj6FLfxRUDZL-2qSrAkEsz2TEnKHJxvl_PB96vBbDoN7vOAhfIoy9knfLR3q_R7SzdG0RmLvokVPoijfnxOlBPN8sbnWvDBgh6WHc9O1OdvR8GS/s1600/214e+color.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh68iAAnQ2FguCqNHgbneHV-0c9NdMtgoj6FLfxRUDZL-2qSrAkEsz2TEnKHJxvl_PB96vBbDoN7vOAhfIoy9knfLR3q_R7SzdG0RmLvokVPoijfnxOlBPN8sbnWvDBgh6WHc9O1OdvR8GS/s1600/214e+color.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">7 more bytes to go and we will fully understand that CGenome section.</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv_Z-HLMYBsUXUYCNbnvMdkYPphFA-8-9kH23Mcd4zuQTBP00Lk5jlguBD4srCWiINhuvBcKalIzltQ8H152zSgs47ZXCDYN9GSxQbZw18qXf-bE8TcXjpyyrYKH4zRz7FGUWrVHy2DTTg/s1600/vocab.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<br />
<br />
So what is in those remaining 7 bytes ?<br />
There is a lot of "00"s in there.<br />
This could either mean longer fields than what we thought ( maybe the .gen section length is "21 4e 00 00" ? )<br />
Or just empty fields, we can't tell for sure for now.<br />
<br />
Let's focus on the "02" value.<br />
Maybe It has something to do with the creature's sex ? or it's life stage?<br />
Both would make good candidates for such a low value. <br />
<br />
Let's export a couple creatures of known characteristics and see how this field varies. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiisUc3Q0zMJaYSV1Jvgr3siKFTJgEc7m_ZC6laJiAoUXJVmcJDhCTH1INP2lcswWaJUN8fklv2hlzmfKdKpQiNSEa4stLgaXxrmS3eA_YGtFjg_S7vD2ZjkH4k0z9Uy6ktEU0JmsTd36D/s1600/malefemale.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiisUc3Q0zMJaYSV1Jvgr3siKFTJgEc7m_ZC6laJiAoUXJVmcJDhCTH1INP2lcswWaJUN8fklv2hlzmfKdKpQiNSEa4stLgaXxrmS3eA_YGtFjg_S7vD2ZjkH4k0z9Uy6ktEU0JmsTd36D/s1600/malefemale.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Comparing the field between a female Norn (above) and a male one (below)</td></tr>
</tbody></table>
<br />
We guessed right, this field varies for creatures of different sex, and the enumeration (1 = male, 2 = female) is consistent of <a href="http://www.gamewaredevelopment.com/downloads/cdn/creatures_caos_guide.pdf">what we know of the game's internal representation of sexes </a>(see C1 CAOS documentation for example)<br />
<br />
We also note that in the following field of "00"s, the last byte before the "gene" word varied between our two sample creatures (it took 00 and 02 as values).<br />
<br />
Given the sample creatures used for the test, my guess is that this field might be the creature age.<br />
Lets use the BORG to create a new norn, export it, save it, forcefully age it , and export again...<br />
(Yeah, I know, I don't really like playing Frankenstein that way, but eh... for science right ?)<br />
What do we get when we compare 4 Creatures being the same norn, forcefully aged a couple seconds apart ?<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGHAakDz7MxzAa8Hz4Pm06jE1Z_-1Jd1494gvByTshEwhEpyIFz-mzx0PTyiwJeUrmhw628sSjE0xrB5fA7FNiii5197HvDHlfWM0QSy_Du7nmt7iZabr7cxR-n_fjsg0HFh0VhupriXLV/s1600/ageing.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGHAakDz7MxzAa8Hz4Pm06jE1Z_-1Jd1494gvByTshEwhEpyIFz-mzx0PTyiwJeUrmhw628sSjE0xrB5fA7FNiii5197HvDHlfWM0QSy_Du7nmt7iZabr7cxR-n_fjsg0HFh0VhupriXLV/s1600/ageing.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The field varies sequentially and in the expected range consistent with the creature ageing </td></tr>
</tbody></table>
That's it !<br />
The last byte before the first "gene" marker is probably the creature's age then.<br />
According to the creature documentation, we know that ages are interpreted 0-7 as : baby,child,adolescent,youth,adult,old,senile,dead from old age.<br />
<br />
We now know what most of the fields mean:<br />
<br />
<img alt="" src="data:image/png;base64,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" /> <br />
<br />
We only have 5 bytes remaining to fully understand that section.<br />
Unfortunately, it's hard figuring out what zeroes might mean...<br />
I went through all my collection of c1 exp files and found no variation of those values whatsoever.<br />
I also tested if they contained an indicator of Norn pregnancy.To no avail.<br />
<br />
So let's just consider for now that those values are always 00 or that surrounding values( .gen section length, age and sex) may instead be coded on more bytes than required.<br />
The later can be confirmed later by reverse engineering the game executable, but this is not worth the trouble for now.<br />
<br />
<h4>
Wrapping things up, the CGenome section structure:</h4>
So , In this first part we learned a couple things.<br />
<br />
- A .exp file is composed of 5 sections, separated by text delimiters("CGallery", "CBrain", "CBiochemistry" and "CGenome").<br />
- The last section ("CGenome") is composed of:<br />
<ul>
<li>The "CGenome" marker, in a CSTRING format.</li>
<li>2 bytes specifying the extractable .gen file length </li>
<li>Two "00" bytes</li>
<li>The Norn Moniker(most likely the instruction of what filename to give to the exported .gen file)</li>
<li>The Norn sex coded on one byte (1= male, 2=female)</li>
<li>3 "00" bytes</li>
<li>The norn lifestage (0-7) on one byte.</li>
<li>A raw .gen file containing the Norns genetic data, that can be simply cut out of the file and pasted in a .gen file.(Observed length for all .gen files seems to always be 20 001 bytes, padded with "00"s at the end.Padding seems optional and the game doesn't complain about shorter .gen files stopping after the "gend" marker )</li>
</ul>
<br />
<br />
That's it for part 1.<br />
In the upcoming parts of this series we will try to make sense of the remaining sections, to the point where we can make something useful of those .exp files.<br />
<br />
<br />The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-4830930348225637942014-11-29T19:59:00.000+01:002014-12-18T00:06:42.606+01:00Parsing Creatures 1 .spr files (Extracting/Manipulating any of the game's graphics)In a <a href="http://sheeslostknowledge.blogspot.fr/2014/02/parsing-creatures-2-s16-files.html">previous article</a> I showed how to read Creatures 2 .s16 files to extract any of the game image data.<br />
In this obvious follow up I will show you how to read out Creatures 1.spr files for the same result.<br />
<br />
The Creatures 1 .spr file format is only marginally harder to parse than the .s16 format.<br />
This is because the .spr files do not directly contain color information for each pixel, but rather an index number, to be used as a lookup index inside an external palette file to get the actual color data.<br />
<br />
Thankfully, Python magic can once again save us most of the hard work and makes extracting an manipulating C1 images files a breeze.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibzvRNAropWAfhCrelMJ2YymWpZVO3GAb1xQ9KAJC_MuNtZ2yVVJfLxVMLMtKzKc0zx1y_oZ_LNICqBv2qImvyTfxYX1m2ohMQIMdhAxt0MV5uS3_fCvcmjM5mQXjl3E5Yuw8iTIxainna/s1600/spr1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibzvRNAropWAfhCrelMJ2YymWpZVO3GAb1xQ9KAJC_MuNtZ2yVVJfLxVMLMtKzKc0zx1y_oZ_LNICqBv2qImvyTfxYX1m2ohMQIMdhAxt0MV5uS3_fCvcmjM5mQXjl3E5Yuw8iTIxainna/s1600/spr1.PNG" height="172" width="400" /></a></div>
<br />
<a name='more'></a><br />
<h4>
The .spr file format</h4>
In C1, all images are stored inside .spr files ("spr" standing for "Sprite").<br />
Each spr file contains one or more images. <br />
The file format for those is quite simple and explained on various places like on the<a href="http://creatures.wikia.com/wiki/SPR_files"> Creatures Wiki</a>.<br />
It also contains many similarities with the .s16 format. <br />
<br />
<br />
The general format for an spr file is as such:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIfa07geVfmjdfYlQ_qrzsamIGGjl_5HIVUai6OhHOXM4iTIfP0LTAsWxbUMpzvUFJeDAt3IXdnvRQ5EtGG6sh0rGHrFNprpucDZ3lRc6cZESSON6wljSWqnAb2zjd4iuSkGzpSVPhkIhq/s1600/Format.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIfa07geVfmjdfYlQ_qrzsamIGGjl_5HIVUai6OhHOXM4iTIfP0LTAsWxbUMpzvUFJeDAt3IXdnvRQ5EtGG6sh0rGHrFNprpucDZ3lRc6cZESSON6wljSWqnAb2zjd4iuSkGzpSVPhkIhq/s1600/Format.png" height="160" width="640" /></a></div>
<br />
Where each sprite header is of the following format (and exactly the same as for .s16 files)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO4592SAJhTp4QkHLpKvE_M1KyFuXeU3y5EY40JxWoaNmIKI3T54jjksFg_2kfqMgF4c6sKJx_NSmOMmTiO2Jfr2erqERYzPoWlztNrSFH5CvPRzsfngD-KIep39hNozALK-o41pPbtHE8/s1600/Header.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO4592SAJhTp4QkHLpKvE_M1KyFuXeU3y5EY40JxWoaNmIKI3T54jjksFg_2kfqMgF4c6sKJx_NSmOMmTiO2Jfr2erqERYzPoWlztNrSFH5CvPRzsfngD-KIep39hNozALK-o41pPbtHE8/s1600/Header.png" height="48" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Where "Offset for data" is the position from the beginning of the whole file where data for the corresponding image is found.<br />
The size of the data field can be easily computed with "image width x image height"<br />
This makes indexing of the file easy, and contrary to the other file
formats studied so far, we can read out single pictures out of spr files
without needing to parse the whole file first.<br />
<br />
Obviously, if you want to extract all images contained within the file, the process can be as simple as:<br />
- Read File count<br />
- Read as much file headers as the file count specifies.<br />
- Read image data in chunks of sizes obtained my multiplying the given image width by it's height.<br />
<br />
<h4>
Interpreting the image data</h4>
<h4>
</h4>
In .spr files, the data section for a given image is just a list of pixels.<br />
Each pixel is encoded on a singe byte.<br />
<br />
This byte acts as a reference to an color definition in a palette.<br />
The palette is stored externally in the "Gamepath\Palettes\palette.dta" file.<br />
<br />
Therefore, for each pixel read out from the image data section, we need to take that pixel value, and read out color information stored in the palette at the position given by the pixel data.<br />
<br />
The <a href="http://creatures.wikia.com/wiki/PALETTE.DTA">format for the palette.dta</a> file is quite simple.<br />
It consists of 256 entries (the number of colors) each made up from a set of 3 bytes, representing Blue, Green, and Red values for that color.<br />
It bears no header whatsoever, so you simply need to read the file data in 3 byte series,256 times to get the RVB values for each color of the palette.<br />
<br />
There's only one catch to it.<br />
For whatever reason, the color definitions bytes stored in this palette are only in the 0-63 range.<br />
Before applying the palette to the picture, we will need to multiply every single byte of the palette by 4 to obtain the original picture.<br />
Failure to do so will result in dark and poorly contrasted images.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic9sd74GVwnaB-qRKkfVE6e6uHAdaCzptbS443WWHMmOCuhsviv-MSHpUWBLuNP9Jyp48s2QaxqFG8sOSWymic2jq74XIJLpwG-AkmnaUlcFVMuDN9qCfPgh1mMt4bfKWxMWlzSS1Rv7E4/s1600/Image_nopal_2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic9sd74GVwnaB-qRKkfVE6e6uHAdaCzptbS443WWHMmOCuhsviv-MSHpUWBLuNP9Jyp48s2QaxqFG8sOSWymic2jq74XIJLpwG-AkmnaUlcFVMuDN9qCfPgh1mMt4bfKWxMWlzSS1Rv7E4/s1600/Image_nopal_2.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Image with a default 256 grayscale palette</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7lchyphenhyphenWLdmtk6uBm5I970WgTLu9a8LwByQrSea2ijsE95G-jTj53mxbexklyUqFGvPhEs6_TI-f_edmlYoxAoU63X5uqRUkPkf0RlWHbuiOu61u_1Ogt2aFtbia3h6CKrDQJN5j3i7oLVQ/s1600/Image_nomum_2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7lchyphenhyphenWLdmtk6uBm5I970WgTLu9a8LwByQrSea2ijsE95G-jTj53mxbexklyUqFGvPhEs6_TI-f_edmlYoxAoU63X5uqRUkPkf0RlWHbuiOu61u_1Ogt2aFtbia3h6CKrDQJN5j3i7oLVQ/s1600/Image_nomum_2.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Image with the raw palette as read from the palette.dta file</td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8bGvCk-S5crbCAPQWyr9muycv9wRRzCI9l1CWCTYb0rUu6LXpf1qw-SPrrELGFlQElMpGo0EtM2Qxyh20Es90VAeatrn-xOm9XhYoOvjUrLKXWlBW33-W4jeAQiIj0KrSmbYSj2hHIhyphenhyphenA/s1600/Image_full_2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8bGvCk-S5crbCAPQWyr9muycv9wRRzCI9l1CWCTYb0rUu6LXpf1qw-SPrrELGFlQElMpGo0EtM2Qxyh20Es90VAeatrn-xOm9XhYoOvjUrLKXWlBW33-W4jeAQiIj0KrSmbYSj2hHIhyphenhyphenA/s1600/Image_full_2.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Image with each byte of the palette multiplied by 4 as required</td></tr>
</tbody></table>
<br />
<span id="goog_1026596991"></span><span id="goog_1026596992"></span><br />
<h4>
Putting it all together</h4>
Once again, here is a small POC showing how to extract all pictures from a .spr file using Python.<br />
This time too we're lucky, as the amazing "PIL" Library supports all the modes we need to get to the image data, making it extraction a one line process.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;">import struct<br />import Image<br /><br />def readLong( readfromfile ):<br /> return struct.unpack("L",readfromfile.read(struct.calcsize("L")))[0]<br /><br />def readWord( readfromfile ):<br /> return struct.unpack("H",readfromfile.read(struct.calcsize("H")))[0]<br /><br />def readSpriteHeader(readfromfile):<br /> header={}<br /> header["Offset"]=readLong(readfromfile)<br /> header["Width"]=readWord(readfromfile)<br /> header["Height"]=readWord(readfromfile)<br /> return header<br /><br /><span style="color: red;"># Open a sample file</span><br />fic=open("raio.SPR","rb")<br /><br /><span style="color: red;">#Read the palette file as a list of bytes.</span><br />palette=[ord(byte) for byte in list(open("Palette.dta","rb").read())]<br /><br />TheFile={}<br /><br /><span style="color: red;"># Read the first 32 bits corresponding to number of images to expect</span><br />TheFile["nbImg"]=readWord(fic)<br />print "The file contains %d images" % (TheFile["nbImg"])<br /><br /><span style="color: red;">#Read out as many image headers as there are files</span><br />for i in range(1,TheFile["nbImg"]+1):<br /> TheFile[i]=readSpriteHeader(fic)<br /> print "Image N° %d starts at %d and is %d x %d" % (i,TheFile[i]["Offset"],TheFile[i]["Width"],TheFile[i]["Height"])<br /><br /><span style="color: red;"># For each of the expected images:</span><br />for i in range(1,TheFile["nbImg"]+1):<br /> <span style="color: red;">#Read the image data</span><br /> TheFile[i]["data"]=fic.read(TheFile[i]["Width"]*TheFile[i]["Height"])<br /> <span style="color: red;">#Create PIL image from the data, "P" means "Palette mode"</span><br /> im=Image.fromstring("P", (TheFile[i]["Width"], TheFile[i]["Height"]),TheFile[i]["data"], "raw","P")<br /> <span style="color: red;"># Apply the game palette ( Remember that according to doc, all bytes of the palette should be multiplied by 4 before usage<br /> # Not doing so will result in dark images</span><br /> im.putpalette([color * 4 for color in palette])<br /> <span style="color: red;"># Output each sprite to a readable format.</span><br /> im.save("Image_"+str(i)+".png")</span></span><br />
<br />
<br />
A<span style="font-family: inherit;">nd there you have it, all images extracted from the .spr file in a commonly usable<span style="font-family: inherit;"> format:</span></span><br />
<span style="font-family: inherit;"><span style="font-family: inherit;">(Re<span style="font-family: inherit;">m<span style="font-family: inherit;">ember that than<span style="font-family: inherit;">ks to python ma<span style="font-family: inherit;">gi<span style="font-family: inherit;">c , you only have to change the file extension <span style="font-family: inherit;">in the last line of code above to output the image into any arbitrary file format.)</span></span></span></span></span></span></span></span><br />
<span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-family: inherit;"> </span></span></span></span></span></span> </span></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib4ekjDq4T_D13_N5jYBGEsoZKPXlhA_RFLIeQDuH0WtVF3OXIsnv0jmcjfmqZqhQBFlHRFWzx9UKWGC256uvDst9lIrKkiEpW6Jj8ghQ7KDRQBcsOG9WcV0BjOSeJaKhBNCbGgfC1v93l/s1600/sprlast.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib4ekjDq4T_D13_N5jYBGEsoZKPXlhA_RFLIeQDuH0WtVF3OXIsnv0jmcjfmqZqhQBFlHRFWzx9UKWGC256uvDst9lIrKkiEpW6Jj8ghQ7KDRQBcsOG9WcV0BjOSeJaKhBNCbGgfC1v93l/s1600/sprlast.PNG" height="325" width="400" /></a></div>
<br />
The corresponding code is stored on the <a href="https://github.com/LoneShee/SLKExamples/blob/master/C1_sprParser_POC.py">LoneShee github</a> along with all other code examples.<br />
<br />
See you next time for some reversing of other C1 and C2 files that unfortunately were not not documented yet.<br />
<br />The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-58234729050374349002014-02-15T16:57:00.000+01:002014-06-27T17:06:25.785+02:00Connecting to the Creatures DDE interface from pythonWe've recently seen how easy it is to <a href="http://sheeslostknowledge.blogspot.fr/2014/02/connecting-to-game-accessing-dde.html">connect to the C1 and C2 DDE interfaces</a> using VB.<br />
<br />
This time we will show how easy it is to connect to those interfaces using python, which will prove useful in upcoming articles.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzdBzBnmnuUMGtJM5CGfJ_cAAUTjYsP7GuTC8DVbWm074eb_TrerrHeejTEVO7q8AxOP5VbCHio3k5Ho1YyQfATcjpl0TQqko4v71mFOxcEYAMBpNyVtrz1cYIJXLmoWXkPezgvjzyajKf/s1600/intro.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzdBzBnmnuUMGtJM5CGfJ_cAAUTjYsP7GuTC8DVbWm074eb_TrerrHeejTEVO7q8AxOP5VbCHio3k5Ho1YyQfATcjpl0TQqko4v71mFOxcEYAMBpNyVtrz1cYIJXLmoWXkPezgvjzyajKf/s1600/intro.PNG" height="346" width="400" /></a></div>
<br />
<br />
Connecting to a DDE server from inside python <strike>is</strike> can be a quick and easy process.<br />
The
hardest part is in acquiring the correct modules to do so, (which can
be a real pain if you take it from the wrong side), there are also a
couple specifics that make debugging the first DDE connections
unreliable.<br />
Fortunately I've sorted those perks out for you,and will show you the single quickest and easy way to connect to the Creatures 1 and 2 DDE interface from python.<br />
<br />
<br />
<a name='more'></a><br />
<br />
The "python for windows extensions" aka "pywin32" is the module that holds the necessary DDE connectors for us.<br />
<br />
To install it be sure to grab a <a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/#pywin32">prepackaged binary copy</a> of pywin32 for your operating system that will save you from the painful process of having to manually install obscure dependencies.<br />
That's it :) <br />
<br />
<br />
From on now, connecting to the Creatures DDE interface becomes as simple as :<br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">import win32ui</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">import dde</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">def SendCommandToGame(command,ExpectedResult=False):</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> <span style="color: red;">"""</span></span></span><br />
<span style="color: red;"><span style="font-family: "Courier New",Courier,monospace;"> This function sends a CAOS command to a C1 or C2 game and returns the result</span></span><br />
<span style="color: red;"><span style="font-family: "Courier New",Courier,monospace;"> You have to specify whether or not the executed command expects output to be returned, as both kinds of commands require different calls</span></span><br />
<span style="color: red;"><span style="font-family: "Courier New",Courier,monospace;"> """</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> server = dde.CreateServer()</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> server.Create("TestClient") <span style="color: red;"># This can be anything or even empty.</span></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> conversation = dde.CreateConversation(server)</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> conversation.ConnectTo("Vivarium", "Anything") <span style="color: red;"># Creatures DDE application is "Vivarium", yours can be anything.</span></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> conversation.Poke("Macro", command+"\x00") <span style="color: red;"># Rembember Creature expects C-style \0 terminated strings as DDE inputs</span></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> if ExpectedResult==True:</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> <span style="color: red;"># If the command returns a result use the Request() method</span></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> rep=conversation.Request("Macro")</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> else:</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> <span style="color: red;"># If the command doesn't a result use the Exec() method</span></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> conversation.Exec(command+"\x00")</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> rep=""</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> server.Destroy()</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> return rep</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"></span></span><br />
<span style="color: red;"><span style="font-family: "Courier New",Courier,monospace;"># Now we can run arbitrary CAOS commands :</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">print SendCommandToGame("dde: getb cnam",True)</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"></span><br />
<br />
<br />
Easy wasn't it ?<br />
You can grab a working example copy of <a href="https://github.com/LoneShee/SLKExamples/blob/master/C1_C2_PythonDDE_example.py">this file</a> on the <a href="https://github.com/LoneShee/SLKExamples">SLK examples github page</a>. <br />
<br />
The only things you should keep in mind are :<br />
- Use the binary (unofficial) packages to install the DDE module<br />
- Be sure to terminate the strings you send to the DDE "Macro" topic with \0 bytes.<br />
- Unfortunately due to limitations in the python DDE module of pywin32, you'll have to use two distinct methods to send your CAOS commands depending on if they output something back or not.<br />
<br />
In upcoming articles we will use this ability to automate most of the tasks we've seen so far, along with a couple others such as :<br />
- Automatically mapping out a Norn's internals using graphviz ( a list of all organs along with all the chemical reactions happening in them :)<br />
- Drawing a fully detailled realtime brain activity map <br />
- Drawing realtime C2 ecology maps<br />
- Many others<br />
<br />
Drop me a line if any if there'are other things you'd like to seeThe Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-74514479100696694042014-02-06T22:40:00.001+01:002014-09-01T13:42:51.695+02:00Parsing Creatures 2 .S16 files (Extracting/Manipulating any of the game's graphics)."Back then" few easy image manipulation libraries were available, making the extraction of game image data an intricate process (that most creature fans/developers tackled in an easy but not very user friendly way as we will expose).Nowadays things got easier.<br />
<br />
In this post I will explain the creatures 2 .s16 file format, and show you how you can now very easily extract any picture from the game using python.<br />
Not only that but we can also harness the power of modern image manipulation libraries to convert the game sprites to any file format we like contrary to most legacy tools only proposing to export images as BMP's and letting us do the conversion work manually.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGcz7g35O2PAp8HsSGTmM78rmK7ff2sd4zNUhc91kD9mEgZrak34KE29jWgLnBaWBRCg8myp4VqYzmbth_zm-cyNVdLqpQGsvrnWEOVSG5ninAl1Yxp-ujuS3-kofyzTAc7piPtwJMyZf4/s1600/intro.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGcz7g35O2PAp8HsSGTmM78rmK7ff2sd4zNUhc91kD9mEgZrak34KE29jWgLnBaWBRCg8myp4VqYzmbth_zm-cyNVdLqpQGsvrnWEOVSG5ninAl1Yxp-ujuS3-kofyzTAc7piPtwJMyZf4/s1600/intro.PNG" height="262" width="400" /></a></div>
<br />
<br />
<a name='more'></a><br />
<h2>
The s16 file format</h2>
In C2, all images are stored inside .s16 files (s16 standing for 16 bit Sprites).<br />
Each s16 file contains one or more images. <br />
The file format for those is quite simple and explained (quite messily by a trainee ??) on <a href="http://www.gamewaredevelopment.com/cdn/CDN_more.php?CDN_article_id=95#sprite">the CDN</a>.<br />
<br />
Let's make a bit more sense of all that as some of the information found there is slightly incorrect and mostly unreadable.<br />
<br />
The general format for an s16 file is as such:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Hmk2zsL_bzDcYc5ioLP4WN9E9UXZizCQGsg_raDHAeoIujWEiYk6iG2-siVhm2FWRNtjTiizmkY6a1QiXU9pIBcNAqKcJBheUK6eMF6rIpbEM1XHLnjwb9lXeqIwvaDV0VEfRCOHEOYm/s1600/Format.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Hmk2zsL_bzDcYc5ioLP4WN9E9UXZizCQGsg_raDHAeoIujWEiYk6iG2-siVhm2FWRNtjTiizmkY6a1QiXU9pIBcNAqKcJBheUK6eMF6rIpbEM1XHLnjwb9lXeqIwvaDV0VEfRCOHEOYm/s1600/Format.png" height="160" width="640" /></a></div>
<br />
Where flags is all zeroes except the last bit.<br />
If last bit is 0, it means the file is in "555" format, if last bit is 1, then the file is in "565" format.<br />
<br />
Each sprite header is composed as such:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja05Uc3D3BGab7TS-xOoCym9j76cxh8jGQPxPmsHxPerSWTVpQ7wv2ct0bbCwW66qcp2A1ic-9-asmMpM7A6sL78WpN3yRWZroTHEyGSgKHI9YpPwyviJH4PzzoiZZSaEt5lyJLwlCmA8K/s1600/Header.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja05Uc3D3BGab7TS-xOoCym9j76cxh8jGQPxPmsHxPerSWTVpQ7wv2ct0bbCwW66qcp2A1ic-9-asmMpM7A6sL78WpN3yRWZroTHEyGSgKHI9YpPwyviJH4PzzoiZZSaEt5lyJLwlCmA8K/s1600/Header.png" height="49" width="640" /></a></div>
<br />
Where "Offset for data" is the position from the beginning of the whole file where data for the corresponding image is found.<br />
The size of the data field can be easily computed with "image width x image height"<br />
This makes indexing of the file easy, and contrary to the other file formats studied so far, we can read out single pictures out of s16 files without needing to parse the whole file first.<br />
<br />
<h2>
So what is that 565 and 555 stuff ?</h2>
You've probably came across the term if you've spent some time in the Creatures community but what is that about ?<br />
Basically 565 and 555 modes describe the way the image data is stored inside the sprites "data" chunk.<br />
<br />
Color images are most often described by packing a red, blue, and green value together to represent each pixel.<br />
All images in C2 are stored in a "16bit" format.<br />
What this means is that each pixel of the final image is stored in 16 bits (aka 2 bytes, aka 1 "word").<br />
The 16 bit boundary is something imposed by the underlying computer architecture that "likes" to operate on values that are powers of two( 2,4,8,16,32,64,128...1024...).Those values will most likely be familiar to you as they're found all over the computer world ( memory sizes, connection speeds...)<br />
<br />
The problem is that 16 is not easily divided into 3 equal parts for storing red, blue and green values for each pixel.<br />
Two common approaches were thus retained for storing those 3 components in 16 bit fields :<br />
<ul>
<li>The "555" approach, means "5 bits for red, 5 bits for green,5 bits for blue". this wastes one bit (the leftmost one) that is always set to 0, and therefore fits 16bit entries.</li>
<li>The "565" approach means "5 bits for red, 6 bits for green,5 bits for blue" , this doesn't readily waste any bits to fall on the 16 bits per entry boundary, but seems to provide the "green" channel additional range compared to the other components.We will end up wasting that additional range anyway by never using those values. </li>
</ul>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaE3TJTbD7PS8c7GC_5zJDXbVNP7awllHwoU_SDuQOmd62RQwQFfG4OVOs0S_ngNh-_dWvBlfpQY4jD3rLDIxhWmOjnssidcqrfkol-WNlcnMB7pMtY9CubaB9XHm4HoOGxPIp7FUVNyva/s1600/4951f44ccd6f9e2f3e5c1d8409188c28.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaE3TJTbD7PS8c7GC_5zJDXbVNP7awllHwoU_SDuQOmd62RQwQFfG4OVOs0S_ngNh-_dWvBlfpQY4jD3rLDIxhWmOjnssidcqrfkol-WNlcnMB7pMtY9CubaB9XHm4HoOGxPIp7FUVNyva/s1600/4951f44ccd6f9e2f3e5c1d8409188c28.png" height="133" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Each pixel is stored on 16 bits</td></tr>
</tbody></table>
<span style="background-color: yellow;"></span><span style="background-color: yellow;"><br /></span>
<br />
<ul>
</ul>
If you are wondering about those wasted bits, yes it remains much more efficient to waste that one bit for each pixel rather than trying to pack those values more tightly and having them not fall on proper power of two boundaries your computer's processor is designed to manipulate.<br />
<br />
Those two methods for storing RGB data using 16 bits for each pixel are nothing Creatures specific, actually this is the exact method used to store image data inside 16bit BMP files.<br />
We will come back to this as a conclusion, but for now let's just fire up python and parse a .s16 file to extract its data.<br />
<br />
<h2>
Parsing an actual .s16 file</h2>
As we've seen in <a href="http://sheeslostknowledge.blogspot.fr/2014/01/parsing-c2-histfiles.html">a previous article</a>, the "History" folder of the C2 game contains files named "Photo_XXX.s16", where XXXX is any creature's 4 character moniker.<br />
Those are where each creatures photo albums are stored.<br />
By parsing those files we can get those pictures out, which might be useful for <a href="http://sheeslostknowledge.blogspot.fr/2014/01/back-to-more-traditionnal-automated.html">a lot of things</a>, such as browsing a creature's photo album even after it's death.(also think about how automatically extracting files and putting them in neatly organised directories could save you much time while designing a new creatures breed)<br />
<br />
We won't even have to dive into the ugly bit level stuff early programmers had to deal with.<br />
By using the python "PIL" library, all of the hard stuff is taken care of for us, and reading out a .s16 file images becomes as simple as :<br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">import struct<br />import Image<br /><br />def readbyte( readfromfile ):<br /> return struct.unpack("B",readfromfile.read(1))[0]<br /><br />def readLong( readfromfile ):<br /> return struct.unpack("L",readfromfile.read(struct.calcsize("L")))[0]<br /><br />def readWord( readfromfile ):<br /> return struct.unpack("H",readfromfile.read(struct.calcsize("H")))[0]<br /><br />def readSpriteHeader(readfromfile):<br /> header={}<br /> header["Offset"]=readLong(readfromfile)<br /> header["Width"]=readWord(readfromfile)<br /> header["Height"]=readWord(readfromfile)<br /> return header<br /><br />#Replace this with your own file: </span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">fic=open("Photo_0BLT.s16","rb")<br /><br />TheFile={}<br /><br />flags=readLong(fic)<br />TheFile["Flags"]=flags<br />print "The file is in " + ["555","565"][flags] +" format."<br /><br />SpriteCount=readWord(fic)<br />TheFile["SpriteCount"]=SpriteCount<br />print "The file has %d sprites" % SpriteCount<br /><br />for i in range(1,TheFile["SpriteCount"]+1):<br /> TheFile[i]=readSpriteHeader(fic)<br /> print "Image N° %d starts at %d and is %d x %d" % (i,TheFile[i]["Offset"],TheFile[i]["Width"],TheFile[i]["Height"])<br /> <br />print TheFile <br /><br />#For each sprite:<br />for i in range(1,TheFile["SpriteCount"]+1):<br /> #Read the corresponding data:<br /> TheFile[i]["data"]=fic.read(TheFile[i]["Width"]*TheFile[i]["Height"]*2)<br /><br /> #BGR;16 is the 565 format, BGR;15 is for 555<br /> if flags==1:<br /> im=Image.fromstring("RGB", (TheFile[i]["Width"], TheFile[i]["Height"]),TheFile[i]["data"], "raw", "BGR;16")<br /> else:<br /> im=Image.fromstring("RGB", (TheFile[i]["Width"], TheFile[i]["Height"]),TheFile[i]["data"], "raw", "BGR;15")<br /><br /> im.show()</span></span><br />
<h2>
</h2>
Easy wasn't it ? We didn''t even need to make sense of the data section.You can grab a working copy of this script <a href="https://github.com/LoneShee/SLKExamples/blob/master/S16Fileextraction_example.py">here</a>.<br />
We could also convert the extracted data into all sorts of arbitrary image formats just by changing the following line :<br />
<br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">im.show()</span></span><br />
<br />
to:<br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">im.save("Image_"+str(i)+".png")</span></span><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEij1xh2cdRlmkr8RmncfBnglwl7djjle8wVBN7ICEpg7eEYjUztdJuGDkzAy_MKmtAyyOfEjJgRP8lmq90K0Gqfh9rx0lu7yqEJO80yr89dBlLLLcbyOxJqJLhtMp6GJYlIslgIjHCgARXA/s1600/results.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEij1xh2cdRlmkr8RmncfBnglwl7djjle8wVBN7ICEpg7eEYjUztdJuGDkzAy_MKmtAyyOfEjJgRP8lmq90K0Gqfh9rx0lu7yqEJO80yr89dBlLLLcbyOxJqJLhtMp6GJYlIslgIjHCgARXA/s1600/results.PNG" height="107" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Yay ! Png's extracted from .s16 files!</td></tr>
</tbody></table>
<br />
<br />
Notice how python magic operates here, automatically converting our image data to the expected format by guessing it from the 3 last characters of the output filename we suggest :)<br />
You could use any common output format such as bmp,jpeg,pdf...<br />
We really have it easy nowdays.I feel like I've been cheating sometimes when using python. <br />
<br />
But how was all this done with the earliest creatures tools ?<br />
<br />
<h2>
The 565/555 easy BMP hack</h2>
You might have noticed if you ever used any of the Creatures s16 conversion or manipulation tools, that most of them exclusively accept to work with "16 bit BMPs".<br />
<br />
The reason behind that is quite simple.<br />
As I've mentioned earlier, the way the pixel data section is stored inside the s16 files is as a series of 16 bit entries, one entry per pixel.<br />
<br />
This happens to be the exact same scheme used to store 16 bit BMP file data.<br />
It then made sense for developers not to waste precious CPU cycles by converting back and forth between images manipulable by standard tools and a proprietary format.<br />
<br />
To convert a .s16 sprite into the corresponding BMP file is as simple as :<br />
<ul>
<li>Parsing the s16 file to get width height and the data blob out of the file.</li>
<li>Composing a working BMP header for the corresponding image size and mode ( this is just a matter of filling in a dozen field values )</li>
<li>Blindly pasting the raw data from the s16 file into the data section of the new BMP. </li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW6HeeoVAmtgqPKcv34yk0Ya38k-T6VTautY428gFMYx2A2U1SuY_kXufkW_FVkAvs5TEyNVKbIR_rrK43_PyDBZ8XxNvgFUdEaIxfmGZh-PlZjr3wFF8QRRHLKVQoHTFk00HquHG5i5rX/s1600/guts.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW6HeeoVAmtgqPKcv34yk0Ya38k-T6VTautY428gFMYx2A2U1SuY_kXufkW_FVkAvs5TEyNVKbIR_rrK43_PyDBZ8XxNvgFUdEaIxfmGZh-PlZjr3wFF8QRRHLKVQoHTFk00HquHG5i5rX/s1600/guts.png" height="173" width="400" /></a></div>
<br />
<ul>
</ul>
Converting back from 16 bit BMP's to .s16 files is the exact same process, only with a much simpler header to generate on the .s16 side. <br />
<br />
This is why most of the image manipulation tools insist on you using only 16 bit BMPs, most of them don't really need to make actual sense of the data they manipulate, just transpose it back and forth between gutted BMP and s16 templates.<br />
<br />
<h2>
What's next ?</h2>
Using PIL is not only about extracting data, the library also offers many image manipulation primitives to draw shapes, resize and crop stuff, apply various filters...Once you've generated a PIL "Image" object you can use all those methods to manipulate your image and write it back.<br />
We will cover the generation of .s16 files later on.Meanwhile here's a small list of possibilities opened by the ability to manipulate the game graphics data :<br />
<br />
<ul>
<li>Extracting Norns pictures from their photo album files.this can be useful for recovering pictures of dead Norns as the games won't let you access to their album after their death.</li>
<li>Understanding to which object any given classifier corresponds.In the game scriptorium, objects are referred to by classifier numbers and never by any explicit name.Mapping a script to the corresponding object can be really tedious.By reading the "Enter scope" script for a given classifier, extracting the CAOS command describing which picture is used, and then visualising the corresponding picture, one could easily get a visual clue of what each classifier is.This critical feature for easing Albian explorations is currently being implemented as a "Wikipedia Nornica" applet inside my <a href="http://sheeslostknowledge.blogspot.fr/p/the-creatures-kontrol-center-ckc.html">upcoming CKC tool</a> (along with automated descriptions of each cob's effects extracted dynamically from the game scripts.No more wondering if eating a given plant will be good or bad, just look it up !).</li>
<li>Extracting pictures from photo albums to incorporate them directly in our <a href="http://sheeslostknowledge.blogspot.fr/2014/01/back-to-more-traditionnal-automated.html">family tree making experiments.</a></li>
<li>Automating image extraction and repacking from/to neat directory structures while working on a new breed.This could save <b>a lot</b> of time while designing sprites for new breeds, and make the overall workflow easier and more user friendly.</li>
<li>Reconstructing creatures tombstones in outside applications from data found in the history files and photo albums.</li>
<li>Automatically exporting your game's photo albums to web pages where visitors can follow your world.</li>
<li>Quickly visualising/automatically generating attachment data files on corresponding sprites while designing a breed.</li>
<li>Generating a one-piece image of the albian background from the background .s16 file.(The file contains hundreds of small sections of the whole world that are stitched together at runtime, but one cannot easily get the whole game background without resorting to third party tools) </li>
<li>Of course any other image related work such as extraction, modification, repacking...</li>
</ul>
I hope you found that useful and that adding this ability to your skillset will open new perspectives in your albian explorations.<br />
<br />
Also, as I'm writing all of this I'm packing all the code snippets into a more robust and usable python library for manipulating the various Creature games files.I will make it available on the<a href="https://github.com/LoneShee/"> site's github </a>as soon as it gets usable enough to be worth sharing.<br />
<br />
<br />
<br />The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-47776632329334108222014-02-03T11:09:00.000+01:002014-02-03T11:14:05.547+01:00Connecting to the Game: accessing the DDE interface with 3 lines of code. (Tutorial)<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2Gg38JGQLf48iNO-4lpcbbYFDU0d98eKz7Ou9LIX9jMU8Yj4W-zzcBMz0DQKIDTa_byo2p8E1_tFBLZF5FXjnjQ_d13vwmYFUHQxbAIr3fk3mnTrvfzQwGKV5MNxgHSOn9Zh-0PkmBHd1/s1600/sample.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2Gg38JGQLf48iNO-4lpcbbYFDU0d98eKz7Ou9LIX9jMU8Yj4W-zzcBMz0DQKIDTa_byo2p8E1_tFBLZF5FXjnjQ_d13vwmYFUHQxbAIr3fk3mnTrvfzQwGKV5MNxgHSOn9Zh-0PkmBHd1/s1600/sample.PNG" height="120" width="320" /></a></div>
<br />
We've been studying a lot of stuff lately, most of it involving running CAOS commands against C1 and C2 games.<br />
C3 has a convenient built-in CAOS console, and various third party tools also propose that feature for C1 and C2.<br />
<br />
But how would you go about implementing this kind of connectivity inside your own programs?<br />
The simplest way to connect to a running C1 or C2 game is through the DDE interface (Dynamic Data Exchange). Also it <b>REALLY is simple</b> even if you barely know anything about programming, so this might be worth checking out.If you never programmed anything and don't have any development tools handy, you could initiate a DDE connection even from inside an Excel macro using VBA.Also the C1 and C2 DDE interfaces being strictly identical, you'll be writing code only once, and be able to use it in both games right now, without any change.<br />
<br />
By sending the game <a href="http://sheeslostknowledge.blogspot.fr/2013/12/caos-snippets.html">some basic CAOS commands</a> and reading their results you can reproduce all of the game functionalities and then some more: reading a Norn's needs and chemicals levels in realtime, selecting Norns and Grendels, carrying them, monitoring their brains,etc...<br />
<br />
This time I show you a very quick overview to get you started in pumping CAOS in and out the C1 and C2 games.More advanced use cases or details will come in futher posts.<br />
<br />
<br />
<a name='more'></a><h2>
</h2>
<h2>
</h2>
<h2>
So what is DDE?</h2>
<span style="font-family: inherit;">DDE stands for Dynamic Data Exchange.It's an old (and in fact deprecated) way to make different processes (executables) talk to each other when run on the same machine.</span><br />
<br />
<span style="font-family: inherit;">It has been since </span><span style="font-family: inherit;">superseded by other communications methods such as COM/OLE </span>or direct shared memory interfaces (such as those used in C3/DS for accomplishing the same task).<br />
<br />
We will be covering DDE here as it really is the easiest way to connect to C1 and C2 games.<br />
Although it is worth noting that both games also support a couple OLE interfaces, which are slightly more intricate to use but offer advanced functions such as actively notifying your application of events happening in game (such as Norns entering and leaving the game for example, which is not supported over DDE).<br />
<br />
Ole interfaces are also what is used by all C1 and C2 kits/applets (which are external applications after all) to interact with the game.<br />
In an upcoming article we will also be covering how to make a proper applet from scratch and integrate it with the game's toolbar using the OLE interface.<br />
But let's get back on DDE tracks for now:<br />
<br />
<br />
<br />
<h2>
The DDE communication model:</h2>
The DDE communication process is based on a server/client model.<br />
The server (the creatures game) announces to the system that it is open to receive and handle requests through DDE.Doing so it registers as an arbitrary name.This is called the <b>"Application"</b>, and both C1 and C2 ask to be called <b>"Vivarium"</b><br />
<br />
The server application will accept various channels of communication.To distinguish between requests originating from various programs, each client uses a different name when connecting the DDE service.<br />
The couple <b>Application + identifier is called the "LinkTopic"</b>, and you can pick any valid Link topic for your application in the form : <b>"Vivarium|Whatever"</b><br />
<br />
Finally the server application can offer various services under an arbitrary set of names.No standard exist as to what names should be use or what they should do.The name of such a service is called the DDE <b>"Item".</b><br />
Both C1 and C2 serve an unique DDE Item called <b>"Macro"</b>; whose net effect is of receiving a CAOS script from the client and sending it back the script output.(The lack of standardisation or ability to ask the service to list offered methods is one of the reasons why the DDE model was abandoned)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBEDgjHMif4lBnI2QBHR4UWDI69F9yWwnkloanqSNfN806LjvMScsIVurOKCnlcGKnW2cZMSl7Dpa0NlVqWyUmFwmbZCFD2Qkf-sZkzbLQJte1QYEi7Lr6-JXNNrfE_QNBZWI6qZXrgINL/s1600/DDE.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBEDgjHMif4lBnI2QBHR4UWDI69F9yWwnkloanqSNfN806LjvMScsIVurOKCnlcGKnW2cZMSl7Dpa0NlVqWyUmFwmbZCFD2Qkf-sZkzbLQJte1QYEi7Lr6-JXNNrfE_QNBZWI6qZXrgINL/s1600/DDE.png" height="109" width="640" /></a></div>
<br />
<br />
A DDE communication happens when a client decides to connect to a DDE service.<br />
It simply provides the operating system the <b>"LinkTopic", </b>it wants to use, along with the "Item" it is interested in, and it also provides optional data as an input for the service.<br />
In our case, our tools will contact the <b>"Vivarium|Myapp" LinkTopic</b>, requesting the<b> "Macro" Item</b>, and passing it arbitrary CAOS script strings as a parameter.<br />
<br />
This is all there is to really understanding the DDE basics, and putting this into practice is even easier.<br />
<br />
<br />
<h2>
Running an actual DDE communication in VB:</h2>
Since the DDE model was deprecated, it's not as easily usable in modern development tools such as .Net as it used to be.<br />
To keep things at their simplest we will therefore use a Visual studio version anterior to the .Net craze, such as visual basic 5 or 6.<br />
If you can't get a hold of such a development environment, the exact same possibilities are offered in the VBA macro interface of any word or excel program from a similar time period.<br />
<br />
In those environments, setting up a DDE link was an easy 4.5 step process:<br />
<br />
<ul>
<li>Create a new VB project, add a textbox (called text1 by default), and a button (called command1 by default)</li>
<li>If you chose to order the proprieties window "by category", you can easily set the text1 textbox properties in the "DDE" category as:</li>
</ul>
<ul><ul>
<li>LinkTopic set to "Vivarium|SLKtestApp" where SLKtestapp is any name you choose.</li>
<li>LinkItem set to "Macro" , this is mandatory.</li>
<li>Don't set LinkMode yet as this would already try a connection even without your application running and would mess up further results.</li>
<li> Your app should now look like this:<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNoVcH99m2PgO-TPepe1FF94ZdU3eaO28ismrbo4utmMwEnePbQkZnAhK9WZEkn3jNSnxftdY2dryyygNMth-AqGoQkoUE7X82FJuwbSPkqeWWXNHxmomtYJGCe9oimdDOVG6viJ9Ke_Li/s1600/1ststep.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNoVcH99m2PgO-TPepe1FF94ZdU3eaO28ismrbo4utmMwEnePbQkZnAhK9WZEkn3jNSnxftdY2dryyygNMth-AqGoQkoUE7X82FJuwbSPkqeWWXNHxmomtYJGCe9oimdDOVG6viJ9Ke_Li/s1600/1ststep.PNG" /></a> </div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
</li>
</ul>
</ul>
<ul>
<li> While you're at it, clear the text1's "text" property to empty the box, and set the Command1's "Caption" property to "Run command" to make it look nicer. </li>
</ul>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirL1H8ybG_HbpHfvQu1SH4KDT3RON15SPSUqoFXq6ySA66y_dVrIA4I0nfVZtzGb8hk2GcMILJv-5TRI2Zy5MKDBai99DU28-jmpRZ4bbK1E34xV1VfQOj7bjhI1gqCqj4ZFX9zSy6kfez/s1600/step2.TIF" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirL1H8ybG_HbpHfvQu1SH4KDT3RON15SPSUqoFXq6ySA66y_dVrIA4I0nfVZtzGb8hk2GcMILJv-5TRI2Zy5MKDBai99DU28-jmpRZ4bbK1E34xV1VfQOj7bjhI1gqCqj4ZFX9zSy6kfez/s1600/step2.TIF" height="238" width="320" /></a></div>
<div style="text-align: center;">
</div>
<ul>
<li> Now double click on an empty area of the form, this should pop up the code editor in the form1's "Form_Load" event. Any code put there will be executed at the application runtime.Here is the good place to specify our DDE ling link type (Manual means that we will be actively querying the DDE service, and that it shouldn't send us anything without us asking for it first). Set this section's code as :</li>
</ul>
<div style="text-align: left;">
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">Private Sub Form_Load()<br />Text1.LinkMode = 2 ' 2 is "manual"<br />End Sub</span></span></div>
<br />
<ul>
<li> The last step is to define the button's action, double click on it and set its "Command1_Click()" event to look like : </li>
</ul>
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">Private Sub Command1_Click()<br />Text1.LinkPoke 'Say "we're ready to recieve some data"<br />Text1.LinkRequest 'Send our command and read response back<br />End Sub</span></span><br />
<br />
<br />
This is it ! you now have a fully working C1/C2 CAOS console.Wasn't that hard was it ?<br />
<br />
Don't forget to run the game first, you can then run your application by pressing <F5>.<br />
Enter any CAOS command in the text box and hit the Run command button, you should get the expected results, with the command's execution result now filling your textbox : <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHoRi6iZkYdajRJziEs0xLimudCnkm-m3v4bdOe4C6q83HtAVha3I5g2pmehv_H_-W4xoylcM6-jBLvZ_EJu4QGnY7mDC4MhYzb-gQQX2K8LH-p6FQCgPkX7j-zEH0XSEr6BXaBEPlRV3v/s1600/command1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHoRi6iZkYdajRJziEs0xLimudCnkm-m3v4bdOe4C6q83HtAVha3I5g2pmehv_H_-W4xoylcM6-jBLvZ_EJu4QGnY7mDC4MhYzb-gQQX2K8LH-p6FQCgPkX7j-zEH0XSEr6BXaBEPlRV3v/s1600/command1.PNG" height="217" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVDB1xahpdP2ZXaazaau1D04Ouq8TXO9oL6Z_Yv8kJSa9lSWQP2lIkQU8hORkll_1aD2B5gFAHy4PAPz-kzggTlGNvkRWjiJfQEH7XlhhGlBVYBsMnncNKqKoRDZJdpdzwCnXC_vzW7wPk/s1600/2ndstep.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVDB1xahpdP2ZXaazaau1D04Ouq8TXO9oL6Z_Yv8kJSa9lSWQP2lIkQU8hORkll_1aD2B5gFAHy4PAPz-kzggTlGNvkRWjiJfQEH7XlhhGlBVYBsMnncNKqKoRDZJdpdzwCnXC_vzW7wPk/s1600/2ndstep.PNG" height="210" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP-nZ1Pz-jYp7NzUEPyTyxnVApKIcEGi6BhNEE74Vcj4fzPUtx9e65Z3VKqiIYANBT2eInOdc-OxOolY8Cu6t25bsu58bWPMUAL8_CEvMEJ3ysZvXeYMwq85wpfkkAHMy47Gz6rY_sg-u5/s1600/command1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<br />
You can now further tune your application to be more user friendly and maybe also add some error handling (as you will probably get a couple nasty errors as soon as you abruptly close the game with your console still running.)<br />
<br />
If you don't know anything about CAOS yet, have a look at my small <a href="http://sheeslostknowledge.blogspot.fr/2013/12/caos-snippets.html">CAOS snippets</a> collection, it contains a batch of readily runnable examples performing common tasks you can use for your tests.<br />
<br />
This might be a good place to notice that C1 (and c2 to a slightly lesser extent) are really picky about your CAOS script syntax, forget the slightest space, comma or such, and the game will most likely instantly crash.<br />
Even if it only gives you an error message and continues to run, I recommend you close and rerun the game before sending any further command as :<br />
<ul>
<li>The game will most likely crash at your next command anyway</li>
<li>Even if it seems to be fine, it will most likely crash in a couple minutes anyway</li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhUvt5KlQVbxSQeN-CElBEhZ7_xhAjlUlLZRrTGfZlZWQ5XFAB1JgOE13vVwxB3V9Wc-gPcZu2as6W5ZYMxvxmZVHPl9ek0fHpLKlabbIHsb2NEc8PfMxkB1Bkwz2UIjb6MgCXFW5Vn7d7/s1600/sample.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhUvt5KlQVbxSQeN-CElBEhZ7_xhAjlUlLZRrTGfZlZWQ5XFAB1JgOE13vVwxB3V9Wc-gPcZu2as6W5ZYMxvxmZVHPl9ek0fHpLKlabbIHsb2NEc8PfMxkB1Bkwz2UIjb6MgCXFW5Vn7d7/s1600/sample.PNG" height="120" width="320" /></a></div>
<div style="text-align: center;">
<br /></div>
Here are some common use commands you might find useful for your early tests:<br />
<br />
Get current creature's name:<br />
<span style="font-family: "Courier New",Courier,monospace;">dde: getb cnam</span><br />
<br />
<span style="font-family: inherit;">Select the Grendel:</span><br />
<span style="font-family: "Courier New",Courier,monospace;">enum 4 2 0,sys: camt,setv norn targ,next</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: inherit;">Get a bunch of usefull stats on all Norns at once:</span><br />
<span style="font-family: "Courier New",Courier,monospace;">dde: getb ovvd</span><br />
<br />
This returns a list of parameters delimited by pipes "|' and is interpreted as such:<br />
Name|Moniker|Sex|Age|Pregnancy|Life Force|Medical condition|Current Room|Xposition|Yposition<span style="font-family: "Courier New",Courier,monospace;">. </span><br />
<br />
Pause the game:<span style="font-family: "Courier New",Courier,monospace;"><br />sys: cmnd 32838</span><br />
<br />
Resume the game<br />
<span style="font-family: "Courier New",Courier,monospace;">sys: cmnd 32837</span><br />
<br />
Toggle infinite scrolling :<br />
<span style="font-family: "Courier New",Courier,monospace;">sys: cmnd 32774</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Carry current item/Norn in the hand:</span><br />
<span style="font-family: "Courier New",Courier,monospace;">edit</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">For other commands see the <a href="http://sheeslostknowledge.blogspot.fr/2013/12/caos-snippets.html">CAOS snippets</a> reference or wait patiently for a full CAOS tutorial.</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">You can reproduce any kit's or third party applet functionality inside your own programs by feeding the game the appropriate CAOS script and then exploiting its response, for example by using the "<span style="color: #ffe599;">driv</span>" command you could mimic the health kit status window:</span></span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"></span></span><br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsThDK1-ruSdArcu27JvZ6f-DPHROBfcG3h27652xhAnrbUV50vVpx99x80MZNe_GJ91nJbnP8Daxbysb2ld13MpoK_jWj4uWBrqScRIJXUt6OORi_PihNTWSOc6iMsL0mBSi6PXxL4QTp/s1600/pulsions.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsThDK1-ruSdArcu27JvZ6f-DPHROBfcG3h27652xhAnrbUV50vVpx99x80MZNe_GJ91nJbnP8Daxbysb2ld13MpoK_jWj4uWBrqScRIJXUt6OORi_PihNTWSOc6iMsL0mBSi6PXxL4QTp/s1600/pulsions.PNG" /></a></span></div>
<span style="font-family: inherit;"><br /></span>
<br />
<h2>
Further stuff:</h2>
<span style="font-family: inherit;">Here is some other DDE information I will be covering in upcoming articles:</span><br />
<br />
<ul>
<li><span style="font-family: inherit;">By using VB or VBA, we've occulted most of the complexity behind setting up a DDE connexion.There are a couple function calls that are used behind the scene for operating the DDE magic, these can be used from any programming language and I will show you how it is done at least in python sometime soon.</span></li>
<li><span style="font-family: inherit;"> </span>DDE links were once a very common way of communication.Even without using VBA, Both Excel and OpenOffice offer a simplified syntax to tie a cell's value to the result of a DDE command.This opens up the potential for having Excel spreadsheets displaying and graphing realtime Norn data, think about how awesome this could be :)</li>
</ul>
<br />
Meanwhile, don't forget to have a look at the awesome <a href="http://double.co.nz/creatures/developerinformation.htm">Chris Double site</a> which is the only online source I've found talking about the various creatures programming interfaces in enough detail to be usable.<br />
It has examples, explanations and code to access the various C1,2,3 interfaces from different programming languages. <br />
<br />
<br />The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-63565117248898173972014-01-30T21:49:00.002+01:002014-02-03T21:05:21.001+01:00Investigating C1 climate (for a huge fail)<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-RXybiuMnv3thnTRS4bH6IMpc8Cy6hAOcQ4IGFw7ZfTULH-2Vn88YTCeofQfnXOdOVlpBy8StqRpQRzxN_3LR7hw-DoG5z_flSZiUB7Sua9JBAsvQu4Shrzu3H50efa9sGlnjyjKpjCf0/s1600/test2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-RXybiuMnv3thnTRS4bH6IMpc8Cy6hAOcQ4IGFw7ZfTULH-2Vn88YTCeofQfnXOdOVlpBy8StqRpQRzxN_3LR7hw-DoG5z_flSZiUB7Sua9JBAsvQu4Shrzu3H50efa9sGlnjyjKpjCf0/s1600/test2.jpg" height="88" width="640" /></a></div>
<br />
We all now C2 has an complex ecology model, where temperature,wind light, radiation and others such parameters dynamically shape the worlds face.<br />
<br />
But did you know that basic ecology elements are also present in C1 to some extent?<br />
Let's find out about those together.<br />
<br />
<br />
<a name='more'></a><br />
So where did it all come from?<br />
One of the very first times ever I opened the C1 genetics kit, I stumbled upon gene 139 called "Get sleepy in the dark"<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwbZcQ8wVD4JSCZj2CTwqNfHSXMMj2rYEUuVBV8pudGZwJS5RDyzItGbHyEAfh6yx7GDTxcyvjPdh07q717T_fy764suaqg-01NdNWDKWkMh4N6dJoLWGL7X0Vqy8AQHFt3V7ZvC9038G-/s1600/sleepy.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwbZcQ8wVD4JSCZj2CTwqNfHSXMMj2rYEUuVBV8pudGZwJS5RDyzItGbHyEAfh6yx7GDTxcyvjPdh07q717T_fy764suaqg-01NdNWDKWkMh4N6dJoLWGL7X0Vqy8AQHFt3V7ZvC9038G-/s1600/sleepy.PNG" /></a></div>
<br />
This got me wondering.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMlhbCQP_cR7Tw9oE88fxioBV_VA3Ge4hOvhIGMDs-uX7Y12gZzxvOnehrpft-ulDqTvBf1-jUWnuBvjfZQvw6uhZByDJ8U403oBGR5sIkw4C6rJ1Dli-3F-xej1LU03V8zUb15QI3SgvT/s1600/sleepy2.TIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMlhbCQP_cR7Tw9oE88fxioBV_VA3Ge4hOvhIGMDs-uX7Y12gZzxvOnehrpft-ulDqTvBf1-jUWnuBvjfZQvw6uhZByDJ8U403oBGR5sIkw4C6rJ1Dli-3F-xej1LU03V8zUb15QI3SgvT/s1600/sleepy2.TIF" /> </a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Sure enough, the gene seems to inject sleepiness into the Norns when the "ambient" light level is low.<br />
<br />
Well, I didn't know C1 had a light level system !<br />
Browsing through the whole C1 Caos guide shows no sign of a "light level" parameter.<br />
It shows that a wind and a temperature parameter exist though!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilw_mD1ZIQz229or-Hx3nbqGmJOTy4J18neuLcnl-svIP69TmcDL3B0FQIDUH9e9k3e5h389I_H6G9zjStaCRAt0RFkTpKImoY4qcSYhKLx_PN50cfHQ9P6eTeC54mmBRG-Cs_MU3CeXLk/s1600/feel+heat.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilw_mD1ZIQz229or-Hx3nbqGmJOTy4J18neuLcnl-svIP69TmcDL3B0FQIDUH9e9k3e5h389I_H6G9zjStaCRAt0RFkTpKImoY4qcSYhKLx_PN50cfHQ9P6eTeC54mmBRG-Cs_MU3CeXLk/s1600/feel+heat.PNG" height="320" width="306" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Norns also seem to be able to perceive external temperature via emitter genes</td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyWQIEY9zK27eKN6IbURUK3hrUGiTq1xNsX8krfGY9BQ7TV1fG7SN8XLOUJFknKSuW6zBsoaPrroQNSpyOMAIGWVW9-4yCn027J0wB87xUxXbMTRX2BYRovP9f0k5eg25Sv1p4HFGNK_oy/s1600/fth.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyWQIEY9zK27eKN6IbURUK3hrUGiTq1xNsX8krfGY9BQ7TV1fG7SN8XLOUJFknKSuW6zBsoaPrroQNSpyOMAIGWVW9-4yCn027J0wB87xUxXbMTRX2BYRovP9f0k5eg25Sv1p4HFGNK_oy/s1600/fth.PNG" height="320" width="248" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Feeling outside hotness should inject the Norn with the corresponding Hotness chemical.</td></tr>
</tbody></table>
<br />
<br />
That looks promising.<br />
What about mapping the whole Albian room layout along with their attributes ( interior/exterior ) and wind and temperature levels ?<br />
<br />
We can get the current games number of rooms by running :<br />
<br />
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;">dde: putv rms# </span></span><br />
<br />
Which returns 29 in my world ( including a couple shelf cobs )<br />
<br />
The following CAOS command can then list all room parameters for us :<br />
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;">setv var1 rms#,loop,dde: putv room var1 0,dde: putv room var1 1,dde: putv room var1 2,dde: putv room var1 3,dde: putv room var1 4,subv var1 1,untl var1 lt 0</span></span><br />
<br />
This outputs a long ugly chain in the form:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">3368|840|3768|1285|3|2288|1565|2451|1860|0|2451|1747|2550|2030|0|7700|0|8352|150|3|7000|0|7700|150|3|6300|0|7000|150|3|5600|0|6300|150|3|4900|0|5600|150|0|6113|1664|0|7350|906|7670|1175|0|72</span><br />
Where the values are in order of appearance: room left, room top, room right, room bottom, room type(0=indoors,1=surface,2=undersea).<br />
<br />
I'll spare you details of implementation this time as it's not that interesting, but by using python and the "PIL" module, we can easily make sense of that data and map in on Albia:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghqZUQQAzli2b2EqzeTSNKF_gCyGmZFPVAWFEm0h0ta_IqLGCGtop2-im4B-2MQFkvwjCsSO2iwQinQm9ChgFDMDevTaq1YPkksw51drqFaks5ALIoDHd4FT3qDGi1PP0XGhHAC_L-aZfJ/s1600/test2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghqZUQQAzli2b2EqzeTSNKF_gCyGmZFPVAWFEm0h0ta_IqLGCGtop2-im4B-2MQFkvwjCsSO2iwQinQm9ChgFDMDevTaq1YPkksw51drqFaks5ALIoDHd4FT3qDGi1PP0XGhHAC_L-aZfJ/s1600/test2.jpg" height="88" width="640" /></a></div>
<br />
Here blue rectangles are outdoor areas, while red ones are indoors.<br />
You might have noticed that no "underwater" room shows up.Actually they do, but they have some strange boundaries expressed with negative numbers that the quick script can't handle.I decided it wasn't worth bothering as only two underwater rooms are defined anyway.<br />
<br />
So ok, we now know which rooms are considered indoors and which ones are outdoors.Not that useful.<br />
Yet it at least shows us that contrary to C2, in C1 the rooms are only sparsely covering the map, and are not interconnected with any common edges.Passing from one room to another is always done through a vehicle.<br />
This explains why using the "<span style="color: #ffe599;">edit</span>" CAOS command in C1 to carry a Norn won't allow you to get it out of the current room ( as Norns have the "roombound" attribute set.In C2 most of the rooms share common edges through which stuff can pass.<br />
<br />
But what about temperature and wind then?<br />
<br />
If you read the C1 caos guide, you'll realise that although "<span style="color: #ffe599;">temp</span>" and "<span style="color: #ffe599;">wind</span>" commands do exist, they are not tied to rooms.<br />
Actually, even in C2, those return "values around current Targ", meaning you can't get a temp value by room, but must pick a target inside the room and check the perceived temperature/wind levels there.(Which explains why in C2 the t° information in the status bar doesn't change when you move around, it represents temperature as perceived by your currently selected creature.)<br />
<br />
What about C1 temperature/wind map ?<br />
The quickest way to find out is to enumerate through all possible objects in the world and get temperature around them while they're current Targ:<br />
<span style="color: #ffe599;"><br /></span>
<span style="color: #ffe599;">enum 0 0 0,dde: putv temp,next</span><br />
<br />
<br />
The result isn't really as expected :<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|........</span><br />
<br />
What about wind ?<br />
<br />
<br />
<span style="color: #ffe599;">enum 0 0 0,dde: putv wind,next</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;">1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1....</span><br />
<br />
Hmmm...<br />
Let's check that against C2 just to be sure our approach isn't flawed:<br />
<br />
Temps:<br />
<span style="font-family: "Courier New",Courier,monospace;">36|69|69|119|66|66|69|68|119|95|36|61|69|47|40|81|36|44|121|69|66|116|78|57|93|93|62|66|36|69|6...</span><br />
<br />
Wind: <br />
<span style="font-family: "Courier New",Courier,monospace;">6|-31|-31|-41|-7|-7|-31|13|-41|-18|6|-20|-31|26|6|-9|6|30|-52|-31|-7|-23|-25|-5|-26|-26...</span><br />
<br />
So yeah, it seems that although present, both temperature and wind are unused in the original game.<br />
That makes for a rather...anticlimactic conclusion for a climatology post.<br />
(And I swear I didn't write the whole article for the sole purpose of this pun)<br />
<br />
What more can we try to save from that failed experiment?<br />
I still would like to understand whether those parameters are just present but unused or if they aren't even implemented.In the later case that would leave us an interesting opportunity to mod the simple C1 Albia to something more complete.<br />
<br />
The way to check that is slightly more involved.<br />
By digging inside the game executable code by itself with IDA, we can quickly locate the part where the CAOS interpreter operates:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv5BpQM3Y63iwmGvGrpoZfqUArNJAK7wv5SbbAYVdT4TxD78htFcfOyNO5vXEvdrCNXVCyeA0Cju7qX7CHCViyidIiVVe09cAKwQHvniixmUukJ36XSPxRo9n8wtHdyX8QhOQrg-9g0Vbp/s1600/IDA.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv5BpQM3Y63iwmGvGrpoZfqUArNJAK7wv5SbbAYVdT4TxD78htFcfOyNO5vXEvdrCNXVCyeA0Cju7qX7CHCViyidIiVVe09cAKwQHvniixmUukJ36XSPxRo9n8wtHdyX8QhOQrg-9g0Vbp/s1600/IDA.PNG" height="417" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This is how the actual C1 CAOS interpreter looks like mapped out in IDA. Each of the green/red branch is the interpreter handling individual CAOS commands, and the bunch of boxes aligned at the botom are the actual functions called by each CAOS keyword to produce the game actions.</td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
I won't go in to much detail here, as raw and dirty reverse engineering might not be that interesting to most of my readers so far.( We will cover that in dedicated posts where this is more relevant)<br />
<br />
<br />
Just as a quick example of what is found in there:<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrsJwVFRUO6th3HEMKk6uVIMU2Oyg9AppZW71praYleL1pHjpXsJADaT3TF4Pe4-iRKNaNlNdY9Zc-j2w8OY7EdAVgtYLg1tsyE4dURmFC0WPmRAtyUVtuI2l5Y4WQGOe4sYYN8QPV1K6Z/s1600/tempida.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrsJwVFRUO6th3HEMKk6uVIMU2Oyg9AppZW71praYleL1pHjpXsJADaT3TF4Pe4-iRKNaNlNdY9Zc-j2w8OY7EdAVgtYLg1tsyE4dURmFC0WPmRAtyUVtuI2l5Y4WQGOe4sYYN8QPV1K6Z/s1600/tempida.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This is the place where the "temp" keyword is detected when parsing CAOS scripts</td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFoG5jKCyDZ3Ecs1TxgCXpLhOPydeRu1yt9oAy0PCnYImeCKQ6TOlXT69ID4LZZj6j3ppGDrdGcE15h0s0J21givvzL3wSPAQ4OYDz1HGM_LYCLx9vKUwpncBS0_1XCW2f_5HsQh_sUbml/s1600/rettemp.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFoG5jKCyDZ3Ecs1TxgCXpLhOPydeRu1yt9oAy0PCnYImeCKQ6TOlXT69ID4LZZj6j3ppGDrdGcE15h0s0J21givvzL3wSPAQ4OYDz1HGM_LYCLx9vKUwpncBS0_1XCW2f_5HsQh_sUbml/s1600/rettemp.PNG" height="296" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">And this is the place where a value to be given "temp" is computed</td></tr>
</tbody></table>
<br />
If we have a peek at this function, we can see that there is some code actually running inside the "CAOSComputeTempVarValue" and supposed to give "temp" a value based on the passed target's coordinates.But in practice, it seems to handle "dead" unused data, and therefore always returns the same value.<br />
This simply shows us that C1 already had some of the bases for the implementation of the C2 model, but that they weren't fully implemented in the released game (Nothing in there seems to feed the temperature/wind map).<br />
This is a dead end for us, we won't be able to implement CAOS stuff that would "reactivate" the unused functions, as the mechanisms that should handle them backstage are inoperant (nothing in the game executable seems to set or manipulate the data those commands read out).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJh0NfTw8Kvz7HlR6_O695wNaGb8-pxphv-BePH33MH27HtW1D4rlWVpaoYeLTASoRMsPhTq5hjHyGjHqgG_Oh1wZ1szXgt5xYLfi3ghV92JcL9rtHqQc5Xeir6DYDRYGJRUSoSSWagGns/s1600/Lie.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJh0NfTw8Kvz7HlR6_O695wNaGb8-pxphv-BePH33MH27HtW1D4rlWVpaoYeLTASoRMsPhTq5hjHyGjHqgG_Oh1wZ1szXgt5xYLfi3ghV92JcL9rtHqQc5Xeir6DYDRYGJRUSoSSWagGns/s1600/Lie.PNG" height="248" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This....is a lie.</td></tr>
</tbody></table>
<br />
That having critically failed, what else can we check on the topic of understanding the environmental stuff?<br />
Unfortunately in C1, the brain applet is pretty much useless and won't allow us to study the brain in an helpful way to determine if the "Creature->Sensimotor->Light level " "air is this hot/cold" environemental parameters actually trigger neurons at any given time inside the Norn.This isn't a big loss as we've shown that there's no variation in temperature or wind in the game anyway.<br />
<br />
One last thing we could check though is the light system.<br />
There's no light command defined in the C1 CAOS documentation.I also checked at the source inside the game executable, and although I've found a couple undocumented functions (nothing really groundbreakingly useful though) nothing light related.<br />
<br />
So what does define the ambient light level supposed to make Norns sleepy (if the mechanism is used at all) ?<br />
Maybe it's the indoors/outdoors qualification of each room that carries an inherent ambient light level acting upon our Norn's inputs?<br />
We could check that. <br />
<br />
The best we could do is to modify a test Norn's genome so light levels directly map to unused chemical level.By moving the Norn around we could then monitor the associated chemical for any changes.(drop me a note if you have any better/complimentary ideas!).<br />
<br />
Let's do this :<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV4ckktV0g7rHx1Xzzj5kgByDkVyoeryW0ZVoLbXlRvChVvQFMwedGvP53GvM3ozmYZ1cABSUViv7fmlChDTsaa9ol8df88xM2xRldklPa2TNUunmLHIdEpGWlbJy4og4OfUytAO_rLwZN/s1600/Luxtestase.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV4ckktV0g7rHx1Xzzj5kgByDkVyoeryW0ZVoLbXlRvChVvQFMwedGvP53GvM3ozmYZ1cABSUViv7fmlChDTsaa9ol8df88xM2xRldklPa2TNUunmLHIdEpGWlbJy4og4OfUytAO_rLwZN/s1600/Luxtestase.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">First we will add a new test chemical that will be easy to track.Don't forget to install the chemicals list.</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0N4ZtwZiQG48HycdKaHqvn8bGYf7crzgHecxhE1cblE8rhbosnnokzd2Tngo7IegrSKa1SjQCZwMdseTNlnx02U2NQVGLZ-1xM14SXUQ8pQDQES5VNO8EE5UnTv25FsnwOFVI45dxIgul/s1600/Newlightgene.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0N4ZtwZiQG48HycdKaHqvn8bGYf7crzgHecxhE1cblE8rhbosnnokzd2Tngo7IegrSKa1SjQCZwMdseTNlnx02U2NQVGLZ-1xM14SXUQ8pQDQES5VNO8EE5UnTv25FsnwOFVI45dxIgul/s1600/Newlightgene.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">...then add a new chemical emitter dedicated to this chemical.</td></tr>
</tbody></table>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOkF3BNlI-lSH-82Vk3TwvPRy2_V6wo6y7rVM4eP3kYfFuDgdCin3QXBvmBAzt_OaLwqAfrgL5yToBIGn3vEuHtWxqchgTZ16UpwlgnA8Ot3SeforeryCSYZoViUAc_JsDjaaLauyz4tXT/s1600/Newlightgene.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOkF3BNlI-lSH-82Vk3TwvPRy2_V6wo6y7rVM4eP3kYfFuDgdCin3QXBvmBAzt_OaLwqAfrgL5yToBIGn3vEuHtWxqchgTZ16UpwlgnA8Ot3SeforeryCSYZoViUAc_JsDjaaLauyz4tXT/s1600/Newlightgene.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Set a smplrate on the low side (often) so you have accurate readings.Set a high gain so you see any variations well.Set a low threshold.Don't forget to make the new chemical a quick decay one too otherwise it will permanently max out at the slightest stimulation.</td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBHQi-iErPZ6ldgD_QhUtQYnC4GQ1uO654LxPPubbet_2WbY9Juc3T6nO4zXnQbZeErF3f4JSKEUJoMoIWs_Ixv-m5UbUkg5uAQVAFFALdeE1yn3pclxvFtLapvlps5UCq88zg2DGhZT2Y/s1600/Newlightgene.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
I'm not showing you the corresponding graphs ingame as they appear slightly confusing and uninformative as illustrations, but once again, the short story is that the graph never changes the slightest bit even after moving the Norn around in every single room in Albia.<br />
The conclusion is then that light levels also seem to be totally inactive in C1 despite being mentioned in the genetics kit.<br />
<br />
My best guess is that all of this was unfinished work in progress that got released with the game, but was not yet in active use at the time.Since C1 and C2 seem to share a lot of common code, I'd say C2 is based directly on an improved version of the C1 engine, and those functionalities only came to full use after the second release( I'd be glad if anyone with "inside" information could confirm that btw.)<br />
<br />
Sorry if you feel that I've wasted your time with a promising article title giving so few exploitable conclusions.But that is how exploration is.Sometimes you find cool stuff to share, sometimes not.Anyway, all of this contributes to its small extent to our overall comprehension of the game series.<br />
<br />
I promise the next posts will contain much more interesting and readily exploitable information :) The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com2tag:blogger.com,1999:blog-1790862754650770452.post-77432713875882289612014-01-26T12:56:00.000+01:002014-01-26T13:03:26.030+01:00Finally, a Creatures 2 Norn autopsy tool<br />
So, we've just learnt how to <a href="http://sheeslostknowledge.blogspot.fr/2014/01/parsing-c2-histfiles.html">extract various information from C2 History files</a>, among which a list of concentrations for a Norn's bloodstream chemicals at time of death.<br />
<br />
We've also learnt how to<a href="http://sheeslostknowledge.blogspot.fr/2014/01/reversing-and-parsing-c2.html"> map a chemical's number to a readable chemical name</a>.<br />
<br />
We can finally get to perform autopsies of dead C2 Norns!<br />
<a name='more'></a><h2>
</h2>
<h2>
C1 autopsies</h2>
As you already might now, the ability to <a href="http://discoveralbia.blogspot.fr/2013/02/the-norn-autopsy-feature-of-cred32.html">perform autopsies on dead creatures</a> exists for C1, if you use cred32's autopsy feature.<br />
Unfortunately, this not only requires that the Norn is still present in the world, but also it's chemicals level keep changing from natural decay, which can give us false results.<br />
<br />
As far as I know, there's no tool allowing us to do the same thing for C2.<br />
We're about to fix that! Moreover our tool won't suffer the same limitations, as in C2 the chemical concentrations at death are available for ever in the creature's history file.<br />
<br />
<h2>
Putting together a C2 autopsy tool</h2>
We will be simply building that on top of our previous work.<br />
Let's pack the 2 required functionalities in two dedicated files: <a href="https://github.com/LoneShee/SLKExamples/blob/master/C2-autopsy-tool-example/Historyfileparser.py">Historyfileparser.py</a> and <a href="https://github.com/LoneShee/SLKExamples/blob/master/C2-autopsy-tool-example/Chemicalsparser.py">Chemicalsparser.py</a>. <br />
<br />
We can now reuse their data thanks to a single line statement.<br />
From there, building a <a href="https://github.com/LoneShee/SLKExamples/blob/master/C2-autopsy-tool-example/Autopsy.py">quick autopsy tool</a> is as simple as :<br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">import Historyfileparser<br />import Chemicalsparser<br /><br />Norns=Historyfileparser.Norns<br />Chemicals=Chemicalsparser.Chemicals<br /><br />print "Dead norns:"<br /><br />for Norn in Norns:<br /> if Norns[Norn]["State"]=="dead":<br /> print Norn +"("+Norns[Norn]["Genus"]+" "+Norns[Norn]["Lifestage"]+")",<br /> <br /><br />who = raw_input("\nEnter a moniker: ").upper()<br />NornChems=Norns[who]["ChemicalsAtDeath"]<br /><br />print "Diagnosing death of "+Norns[who]["Name"] + "("+Norns[who]["Moniker"]+"):" # He's not a moniker! In death, members of project CAOS do have a name.<br />print "Subject data: " + Norns[who]["Gender"] +" " + Norns[who]["Genus"] + "\t Dead as:" + Norns[who]["Lifestage"]<br />print "-"*50<br /><br />if Norns[who]["Lifestage"]=="Kaputt":<br /> print "Creature most likely died of old age"<br /><br />for num, chem in enumerate(NornChems):<br /> if Chemicals[num] !="" and Chemicals[num] !=" ":<br /> print (Chemicals[num] +":"+str(ord(chem))+"\t").expandtabs(20),<br /> if num % 5 ==0: # "if current chemical is a multiple of 5"<br /> print "" # then add newline<br /> </span></span><br />
<br />
Not that hard was it ?<br />
<br />
<h2>
Testing it </h2>
Runnig the script produces following output :<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Dead norns:<br />2TAV(Ettin Adolescent) 8CWN(Ettin Kaputt) 7TML(Ettin Kaputt) 8CIH(Grendel Child) 1JWF(Grendel Child) 5CHG(Grendel Baby) 0BLT(Grendel Old) </span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><br />Enter a moniker: <span style="color: red;">8cih</span></span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: red;"> </span><br />Diagnosing death of <No name>(8CIH):<br />Subject data: male Grendel Dead as:Child<br />--------------------------------------------------<br />Pain:0 Need for Pleasure:241 Hunger:255 Coldness:0 Hotness:40 <br />Tiredness:0 Sleepiness:255 Loneliness:7 Crowded:93 Fear:0 <br />Boredom:0 Anger:76 Sex Drive:0 Injury:0 Suffocation:0 <br />Thirst:0 Stress:0 Pain Increase:0 Need for Pleasure Increase:0 Hunger Increase:0 <br />Coldness Increase:0 Hotness Increase:0 Tiredness Increase:0 Sleepiness Increase:0 Loneliness Increase:0 <br />Crowded Increase:0 Fear Increase:0 Boredom Increase:0 Anger Increase:0 Sex Drive Increase:0 <br />Injury Increase:230 Suffocation Increase:0 Thirst Increase:0 Stress Increase:0 Pain Decrease (Endorphin):0 <br />Need for Pleasure Decrease:0 Hunger Decrease (Saccharin):0 Coldness Decrease:0 Hotness Decrease:0 Tiredness Decrease:0 <br />Sleepiness Decrease:0 Loneliness Decrease:0 Crowded Decrease:0 Fear Decrease:0 Boredom Decrease:0 <br />Anger Decrease:0 Sex Drive Decrease:0 Injury Decrease:0 Suffocation Decrease:0 Thirst Decrease:0 <br />Stress Decrease:0 Reward:18 Punishment:0 Reinforcement:0 ConASH:0 <br />DecASH1:0 Reward Echo:0 Punish Echo:0 DecASH2:0 Lactate:3 Pyruvate:3 Glucose:74 <br />Fatty Acid:1 Glycogen:194 Starch:0 Fat:0 Adipose Tissue:210 <br />Life:193 Muscle Tissue:142 Triglyceride:46 Protein:0 Amino Acid:8 <br />Dissolved carbon dioxide:6 <br />91:0 Urea:0 Ammonia:0 Oxygen:244 <br />Air:9 Water:29 Energy:14 ATP:0 ADP:255 <br />myoglobin:0 oxymyoglobin:0 Bilin:0 Oestrogen:0 <br />Testosterone:0 Gonadotrophin:0 Progesterone:0 Inhibin:0 LH:0 <br />FSH:0 Steroidone:0 Cholesterol:149 Arousal Potential:0 Mating Pheramone:0 <br />Species Pheramone:0 Parent Pheramone:0 Child Pheramone:0 Sibling Pheramone:0 Opposite Sex Pheramone:0 <br />Norn Smell:0 grendel smell:0 ettin smell:0 Heavy Metals:5 <br />Cyanide:9 Belladonna:0 Geddonase:0 Glycotoxin:0 <br />Fullness:0 Vitamin E:0 <br />Vitamin C:0 Bile Acid:11 Insulin:0 Glycogen Synthetase:0 Dehydrogenase:0 <br />Prostaglandin:0 EDTA:0 sodium thiosulphite:0 Arnica:0 tyrosine:0 triptophan:0 Alcohol:0 <br />Dancing:0 Adrenaline:0 Hexokinase:0 Activase:0 Turnase:0 <br />Collapsase:0 downatrophin:0 upatrophin:0 Phosphoglycerokinase:0 Protease:0 <br />Histamine A:0 Histamine B:0 Sleep toxin:0 Fever toxin:0 <br />unknown toxin:0 unknown toxin:0 unknown toxin:0 unknown toxin:0 Antibody 0:97 <br />Antibody 1:104 Antibody 2:0 Antibody 3:110 Antibody 4:97 Antibody 5:0 <br />Antibody 6:0 Antibody 7:0 Antigen 0:0 Antigen 1:0 Antigen 2:0 <br />Antigen 3:0 Antigen 4:0 Antigen 5:0 Antigen 6:0 Antigen 7:0 </span></span><br />
<br />
Output is a bit messy as the chemicals names length varies wildly, but all required information is now there :).<br />
<br />
<h2>
Cause of death </h2>
I'd say the poor Grendel died of cyanide poisoning,inside the volcano where most of the Grendels end up and deathcap mushrooms grow abundantly.<br />
Despite his very high hunger, he still had good glycogen reserves, but no way to use them (no glycogen synthetase) which seems to indicate brutally stopped organs and digestive process (coma).<br />
Despite having contracted multiple illnesses, only residual antibodies and no antigens were present at death time (antigens have relatively slow decay rates, so if the Grendel was still ill at the time of death we would most likely have found at least some residual antigens.) <br />
Energy is very low, and ATP is 0 which is a <a href="http://sheeslostknowledge.blogspot.fr/2014/01/investigating-effects-of-cyanide.html">characteristic effect of cyanide poisoning</a>.<br />
We now that the slightest amount of it can be fatal especially on Grendels and Ettins that lack the ability to decay or eliminate it even given the right antidote.<br />
Most likely, the cyanide intake ate away the Grendel's energy, putting it in the coma, stopping it's organs, which would explain why some of the digestive processes were stopped due to lack of appropriate chemicals while some nutrients were still available.Brain being critically sensitive to low energy levels probably shut off soon after, leading to the Grendel's demise.A sad yet pretty common case of Grendel death. <br />
<br />
<ul>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Hunger:255</span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Fullness:0</span></span></span></span> </span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Starch:0 </span></span></span></span> </span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Hotness:40</span></span></span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Cyanide:9</span></span></span></span></span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Energy:14 </span></span> </span></span> </span></span></span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Glycogen:194 </span></span></span></span></span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Glycogen Synthetase:0 </span></span> </span></span></span></span></span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">ATP:0,ADP:255 </span></span> </span></span></span></span></span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Antibody 0:97 </span></span></span></span></span></span></span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Antibody 1:104 </span></span></span></span></span></span></span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Antibody 3:110 </span></span></span></span></span></span></span></span></li>
<li><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Antibody 4:97 </span></span></span></span></span></span></span></span></li>
</ul>
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span></span></span> </span></span></span></span><br />
<ul>
</ul>
<h2>
Closing words</h2>
<br />
Once again, this was just a quickie to show you how easy it can be to write your own tools for when none are available or if you have special needs, this obvously isn't consumer grade code but merely a proof of concept.<br />
<br />
If you really need such a tool for everyday use though, don't worry, as one should come out soon as a part of <a href="http://sheeslostknowledge.blogspot.fr/p/the-creatures-kontrol-center-ckc.html">my Creatures Kontrol Center</a> :). <br />
<br />
Meanwhile, keep in mind that the data we're extracting are the chemicals right at time of death.<br />
If the creature died of some kind of poisoning, there's a chance that by the time the Norn actually dies, the culprit chemical might be gone, and the creature dead from side effects of prolonged coma.You might have to correlate other factors to understand what actually happened (low glycogen levels but no hunger ? this might be a glytoxin poisoning case even if no more glytoxin remains in the Norns body)<br />
But these are the quirks of the Norn autopsy art which is yours to hone from on now.<br />
<br />
As some of you might get bored of all this strictly techie stuff, I'll try to take a small break from those gory implementation details for a few posts and show you some more Albian exploration in the upcoming ones :) .<br />
<br />
Meanwhile (don't actually) enjoy messing around with dead pets !The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-74042743774537503402014-01-24T23:17:00.000+01:002014-01-24T23:45:21.497+01:00Getting C2 chemicals descriptions (chemicals.def file format)What a sneaky bastard I am.<br />
This was supposed to be a C2 Norn autopsy article! (I swear I'm not doing that to avoid awarding anyone the promised carrot.)<br />
<br />
I just realised something was still missing from the last article.<br />
In the <a href="http://sheeslostknowledge.blogspot.fr/2014/01/the-creatures-1-chemicalstxt-file-format.html">C1 chemicals information article</a> we were able to pull out both chemical names and descriptions from the chemicals.txt file.<br />
<br />
So where's that information in C2 ?<br />
<br />
<a name='more'></a> It doesn't seem to exist in the default game, but you can find it in the C2 genetics kit, hiding as the "chemicals.def" file (pretty bad disguise if you ask me).<br />
<br />
If we open that file up in a hex editor, it will look strangely familiar :<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwKcFHTQ2qNTRqo9Vj46J_PEXP_ua2ToObCB0xfPh7qIlBRCHIFhSHMjmGk7Pt5mtHMI8QxCIRNQEkUe7PjHmRIuq3ogpHumtyyQ43WlFIEIZxH3XHeDw7v7BX_0Gs3-g-cz5kj2RvMKjW/s1600/defs.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwKcFHTQ2qNTRqo9Vj46J_PEXP_ua2ToObCB0xfPh7qIlBRCHIFhSHMjmGk7Pt5mtHMI8QxCIRNQEkUe7PjHmRIuq3ogpHumtyyQ43WlFIEIZxH3XHeDw7v7BX_0Gs3-g-cz5kj2RvMKjW/s1600/defs.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A 2 byte "\x00\x00" header before the first entry this time.</td></tr>
</tbody></table>
<br />
The file is also a flat collection of string entries with a 2 byte header. ( this time it's "00 00" )<br />
The only change is that the length information prefixing each entry is not a single byte anymore but rather a word (2 bytes).<br />
<br />
You can see that the length for "Pain" is now described as "04 00" rather than simply "04" as in the other files.<br />
It makes sense if you want to use descriptions longer than 256 characters (the maximum value for a single byte).<br />
But it also means that those aren't strictly the "Cstring" type <a href="http://www.gamewaredevelopment.com/cdn/CDN_more.php?CDN_article_id=95#terms">described over at the CDN</a>.<br />
(Check out the <a href="http://sheeslostknowledge.blogspot.fr/2014/01/parsing-c2-histfiles.html">C2 History file parsing post</a> for details on long Cstrings if you don't remember why)<br />
<br />
If we get to the end of the chemicals list, we can find a 4 byte "\x00\x00\x00\x00" separator, and then a list of the chemicals descriptions in the same order as the chemicals themselves.<br />
This is very similar to the C1 chemicals.txt format. ( Also we can be sure that those 4 bytes are an actual separator and not 2 empty string entries, since we've seen that "Antigen 7" is the last of the chemical list in the previous article) <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFO5iO4zI1mMqGEx3zgO5mgCv0UxBgwEdYxhhi38baS0hODzVl4qZUGEWoVBzEGkFhD9r6Gj_2MbVWFNOvp8Q4iFISAg7mGfVwIjiP0hwt7q3cICRRX0J4P_uN5WKh0rMHY3Ie5frYJeC9/s1600/last2.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFO5iO4zI1mMqGEx3zgO5mgCv0UxBgwEdYxhhi38baS0hODzVl4qZUGEWoVBzEGkFhD9r6Gj_2MbVWFNOvp8Q4iFISAg7mGfVwIjiP0hwt7q3cICRRX0J4P_uN5WKh0rMHY3Ie5frYJeC9/s1600/last2.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">After the 4 bytes "\x00\x00\x00\x00" separator, begins the list of chemical description entries.As usual these are strings prefixed with their length, except that now their length is coded as words( 2bytes) rather than bytes.</td></tr>
</tbody></table>
<br />
I won't be going into the details of how to write the corresponding parser for this file as you could easily extrapolate that from the <a href="https://github.com/LoneShee/SLKExamples/blob/master/ParseC1chemicalsfile_example.py">C1 chemicals.txt</a> and <a href="https://github.com/LoneShee/SLKExamples/blob/master/C2chemicalsparser_example.py">C2 allchemicals.str parsers</a>.<br />
This will probably be a good reader exercise at this point.<br />
(Also I'm to lazy to write it right now, this being my second article in a row this evening.And I find that the information it contains is not that vital at this point anyway)<br />
<br />
Just to sum things up, here is the formal chemicals.def file format, similar to the C1 one, with <span style="color: red;">chemical entries</span>,<span style="color: blue;">a separator</span>, and then <span style="color: #93c47d;">chemicals description entries</span>, the only difference being that here all string entries are prefixed with their length coded on 2 bytes rather than one.<br />
<br />
<span style="color: red;"><2 byte header> : always "\x00\x00"</span><br />
<span style="color: red;"><2 bytes "chemical1 length">< X bytes chemical1 name></span><br />
<span style="color: red;"><2 bytes "chemical2 length">< X bytes chemical2 name></span><br />
<span style="color: red;">...</span><br />
<span style="color: red;"><2 bytes "chemicalN length">< X bytes chemicalN name></span><br />
<span style="color: blue;"><4 bytes separator> : always "\x00\x00\x00\x00" </span><br />
<span style="color: #93c47d;"><2 bytes "chemdesc1 length">< X bytes chemical1 description></span><br />
<span style="color: #93c47d;"><2 bytes "</span><span style="color: #93c47d;"><span style="color: #93c47d;">chemdesc2 </span>length">< X bytes chemical2 </span><span style="color: #93c47d;"><span style="color: #93c47d;">description</span>></span><br />
<span style="color: #93c47d;">...</span><br />
<span style="color: #93c47d;"><2 bytes "</span><span style="color: #93c47d;"><span style="color: #93c47d;">chemdescN </span>length">< X bytes chemicalN </span><span style="color: #93c47d;"><span style="color: #93c47d;">description</span>></span><br />
<br />
<br />
<br />
Ok, this time I promise, the next article will really be about performing C2 autopsies !<br />
<br />
<br />The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-12395781076127252422014-01-24T22:26:00.002+01:002014-01-25T15:39:11.744+01:00Reversing and Parsing C2 allchemicals.str file format<br />
Aright, we already covered how to obtain an up to date list of Chemical numbers and names inside our programs by <a href="http://sheeslostknowledge.blogspot.fr/2014/01/the-creatures-1-chemicalstxt-file-format.html">extracting it from C1</a> game files.<br />
<br />
Obviously this is an ability of much practical value for C2 too, so let's see how we could do that now.<br />
I haven't found the allchemicals.str file format described anywhere so far, but the format is simple enough so reversing it should be Norn's play for us at this point :) <br />
<br />
<a name='more'></a><br />
<br />
Our
most likely candidate for that information (if you ever tried to open a
couple of creature game files in a text editor) will be the
"allchemicals.str" file from the game directory.<br />
Depending on your
country, you might rather be interested in the "allchemicalsDE.str" or
"allchemicalsFR.str" files, containing the same information in various
languages.<br />
<br />
So what do we get by opening the file in a hex editor ? (I'm using <a href="http://mh-nexus.de/en/hxd/">HxD</a>
by the way, it's full of useful features such as diffing between
files, or the ability to browse a process memory footprint rather than
files)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNkxNBYjFilOtMDK8rkGh1Kd0VlG0VY84e5C5NysVZiZUeX9x2XtaF3FzkXvrSiu7AjZ4lUnjOaoLjjBIlgu6PFA-lUBiejANluq19vumyDxqSL3QQMKjXX-9P3qkOcg6sggIWxLMpzlDY/s1600/hex.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNkxNBYjFilOtMDK8rkGh1Kd0VlG0VY84e5C5NysVZiZUeX9x2XtaF3FzkXvrSiu7AjZ4lUnjOaoLjjBIlgu6PFA-lUBiejANluq19vumyDxqSL3QQMKjXX-9P3qkOcg6sggIWxLMpzlDY/s1600/hex.PNG" /></a> </div>
<br />
The first thing we notice is the various chemical names, separated by some kind of 1 byte space.<br />
This should look familiar to you if you followed <a href="http://sheeslostknowledge.blogspot.fr/2014/01/the-creatures-1-chemicalstxt-file-format.html">the preceding</a> file format parsing <a href="http://sheeslostknowledge.blogspot.fr/2014/01/the-creatures-1-chemicalstxt-file-format.html">articles</a>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi30vi4R6u-hRJcHJsvC3OnA7R2JBPt5sSzU8J4DjurLUpn1M4qUuCxjHL9C_cUoK6yd0IlM3DJi7zF2CX2Y7aFaRuuXN5o6kLSwxOiPmLuxWyTABt3kr2_1Mp55IAtLt5ubJjDnjfQZ2Uk/s1600/format.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi30vi4R6u-hRJcHJsvC3OnA7R2JBPt5sSzU8J4DjurLUpn1M4qUuCxjHL9C_cUoK6yd0IlM3DJi7zF2CX2Y7aFaRuuXN5o6kLSwxOiPmLuxWyTABt3kr2_1Mp55IAtLt5ubJjDnjfQZ2Uk/s1600/format.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">0A in hex is 10, which perfectly matches length of the "Loneliness" string</td></tr>
</tbody></table>
<br />
A quick check confirms that the 1 byte value before each readable string matches it's length.<br />
As we've seen before, this is what the CDN calls "Cstrings" entries, and they are pretty easy to read out.<br />
There doesn't seem to be any kind of additional ID or index by entry whatsoever, which is consistent with our knowledge of Creatures file formats.We can safely assume that those entries are read out sequentially and numbered as we go.<br />
<br />
So, what else is in there if we consider all those text entries understood ?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqVhG40YifhvPW7yEceqPzOFR23aVgq0xM1Gk-UMeML4u01HdjCKjRrN7Y9yWSkbREeyiMYl2ogvx0hcVAjzZ858kFSmNeG-29s0oeBlq3lqnkCamBpivASB_N9nCzs-Z7lked3urhpG-7/s1600/end.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqVhG40YifhvPW7yEceqPzOFR23aVgq0xM1Gk-UMeML4u01HdjCKjRrN7Y9yWSkbREeyiMYl2ogvx0hcVAjzZ858kFSmNeG-29s0oeBlq3lqnkCamBpivASB_N9nCzs-Z7lked3urhpG-7/s1600/end.PNG" /></a></div>
<br />
If we jump to the end of the file, we can see the file ends abruptly at the Antigen7.<br />
There doesn't seem to be any chemical description included further down in this file as was the case with the C1 chemicals.txt file.That's one less thing for us to worry about.<br />
<br />
The batch of 0's in the middle of the file looks like a collection of empty records.<br />
We can confirm that by firing up the C2 genetics kit, and going to the biochemistry tab.<br />
Sure enough it shows that a whole set of chemicals are unused between "Upatrophin" and "Histamine A",which kind of confirms our guess.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM3w93QHbBWvMA02JMJ6sZF_as33fcyauw4cIYsyhN24UMvDOkk10UhaE1-yP8jKmMVyAaOUeKFisv8hqK92CI0hRxx7wDx6CGYBJiLrA2mRWH0yYCi6HpO-UunczLOD5qE9Zbjjr_7FZ8/s1600/hole+1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM3w93QHbBWvMA02JMJ6sZF_as33fcyauw4cIYsyhN24UMvDOkk10UhaE1-yP8jKmMVyAaOUeKFisv8hqK92CI0hRxx7wDx6CGYBJiLrA2mRWH0yYCi6HpO-UunczLOD5qE9Zbjjr_7FZ8/s1600/hole+1.PNG" height="117" width="320" /></a></div>
<div style="text-align: center;">
...</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgey3K4d5k-YUBxUwlK9J1P7Pp2vVOUl8Uwb1MBupgoZ2ZJ34RAhg09F748lcypbvPkqoH6YG-YIzTVR4am2-9tLNEdTnN-apQiYuvh_V6L9DXoXBPQLCwAa_CeVdKOBnG8nAIxLpzw4Ej1/s1600/hole+2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgey3K4d5k-YUBxUwlK9J1P7Pp2vVOUl8Uwb1MBupgoZ2ZJ34RAhg09F748lcypbvPkqoH6YG-YIzTVR4am2-9tLNEdTnN-apQiYuvh_V6L9DXoXBPQLCwAa_CeVdKOBnG8nAIxLpzw4Ej1/s1600/hole+2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgey3K4d5k-YUBxUwlK9J1P7Pp2vVOUl8Uwb1MBupgoZ2ZJ34RAhg09F748lcypbvPkqoH6YG-YIzTVR4am2-9tLNEdTnN-apQiYuvh_V6L9DXoXBPQLCwAa_CeVdKOBnG8nAIxLpzw4Ej1/s1600/hole+2.PNG" height="90" width="320" /></a></div>
<br />
<br />
What's left then?<br />
If we jump right at the beginning of the file, we can see there are 2 unknown bytes of data before the first entry:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYNLnD73Ac4UlLYIPed5vjNPp-LWUhULD1WbNhbLJIInZ0ueuzNNul3eueiPOiPhaqdgZDi0x4CuG7CYBqkOjjip5Wd3jemyCrDjV6IaIXTHvgMr78ZAnNm6Jtzxc62jpS6z2Tir4cG5fI/s1600/Begining.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYNLnD73Ac4UlLYIPed5vjNPp-LWUhULD1WbNhbLJIInZ0ueuzNNul3eueiPOiPhaqdgZDi0x4CuG7CYBqkOjjip5Wd3jemyCrDjV6IaIXTHvgMr78ZAnNm6Jtzxc62jpS6z2Tir4cG5fI/s1600/Begining.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">"<Nothing>" is 9 bytes long, but what's "00 01" ?</td></tr>
</tbody></table>
<br />
It would have been a reasonable place to look for information such as a number of entries, file size or some kind of header.<br />
<br />
There's not many ways one could interpret "00 01" though.Whichever format you'd choose to read that as (whether it is 2 bytes, one word, little or big endian order...) it wouldn't contain any relevant information.<br />
Also it's always the same entry between our localised variants of the files (so it's definitely not a "language" flag).<br />
We can safely assume it's either unused or some kind of header meant to recognize the file type.<br />
(which is also what <a href="https://github.com/ccdevnet/openc2e/blob/master/src/backends/qtgui/ChemicalSelector.cpp">openc2e developpers seem to have recognized this as</a>).<br />
<br />
Is that all ?<br />
It seems so :)<br />
The file doesn't seem to contain anything more than a 2 byte header, and a succession of "Cstring" type entries.( I'd still rather call those Pascal strings...but whatever...).<br />
We already know how to read those out in python from our preceding articles, so the whole parsing of the file should be pretty quick as most of this is code we've already used:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><br />import struct<br /><br />def readword( readfromfile ):<br /> return struct.unpack("H",readfromfile.read(2))[0]<br /><br />def readCstring (readfromfile):<br /> byte=readfromfile.read(1)<br /> if byte=="":<br /> return None<br /> strlength = struct.unpack("B", byte)[0]<br /> if strlength == 0xff:<br /> strlength = struct.unpack("H", readfromfile.read(2))[0]<br /> return readfromfile.read(strlength)<br /><br />chemfile=open("allchemicals.str","rb")<br />Chemicals=[]<br /><br /><br />Header=readword(chemfile)<br /><br />entry=readCstring(chemfile)<br />while entry != None:<br /> Chemicals.append(entry)<br /> entry=readCstring(chemfile)<br /><br />for num, chem in enumerate(Chemicals):<br /> if str(num)!=chem and chem !="": # skip empty chemicals that might either be empty strings, or the chemical number(that's how the genkit names unknown chemicals)<br /> print str(num) +": "+chem</span></span><br />
<br />
You can get the example script <a href="https://github.com/LoneShee/SLKExamples/blob/master/C2chemicalsparser_example.py">here</a>.<br />
<br />
This of course produces the expected result:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">0: <nothing><br />1: Pain<br />2: Need for Pleasure<br />3: Hunger<br />4: Coldness<br />5: Hotness<br />6: Tiredness<br />7: Sleepiness<br />8: Loneliness<br />9: Crowded<br />10: Fear<br />11: Boredom<br />12: Anger<br />13: Sex Drive<br />14: Injury</span><br />
....<br />
<br />
Comparing our results to a known reference (the C2 genetics kit) shouldn't get us any unexpected surprises:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj26zDRSyM4SwhGVzK0Z9jnu_WmFkmXScRrSWDJPh0uCBAC33EqC3pDd6jEcjxopg3bgx6ohHEvWYpgJVQLI4yzVzSgyMuGcXeoSBJwDOmGlPe5qq_DeI2LQJz85rXcH-9RA0uH4MB67-eV/s1600/last.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj26zDRSyM4SwhGVzK0Z9jnu_WmFkmXScRrSWDJPh0uCBAC33EqC3pDd6jEcjxopg3bgx6ohHEvWYpgJVQLI4yzVzSgyMuGcXeoSBJwDOmGlPe5qq_DeI2LQJz85rXcH-9RA0uH4MB67-eV/s1600/last.PNG" /></a></div>
<br />
<br />
And chemicals names can now be easily retrieved from the list by indexing them by number:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">>>> <span style="color: red;">print Chemicals[1]</span><br />Pain<br />>>> <span style="color: red;">print Chemicals[72]</span><br />Glycogen<br />>>> <span style="color: red;">print Chemicals[170]</span><br />Alcohol</span><br />
<br />
It also works on "le liste des produits chimiques" und "Das <span class="short_text" id="result_box" lang="de"><span class="hps">Chemikalien liste":</span></span><br />
<span class="short_text" id="result_box" lang="de"><span class="hps"><br /></span></span>
<span style="font-family: "Courier New",Courier,monospace;">1: Douleur 1: Schmerz<br />2: Besoin de plaisir 2: Genußbedürfnis<br />3: Faim 3: Hunger<br />4: Sensation de froid 4: Kälte<br />5: Sensation de chaleur 5: Hitze<br />6: Fatigue 6: Müdigkeit<br />7: Endormissement 7: Schläfrigkeit<br />8: Solitude 8: Einsamkeit<br />9: Bondé 9: Beengtheit<br />10: Peur 10: Angst<br />11: Ennui 11: Langeweile</span><br />
<span style="font-family: "Courier New",Courier,monospace;">...</span><br />
<br />
If you were following my last articles, you should already know where all of this is going.<br />
We've acquired the ability to <a href="http://sheeslostknowledge.blogspot.fr/2014/01/parsing-c2-histfiles.html">extract a list of chemical concentrations found at death</a> inside a creature, and we can now match chemical numbers to meaningfull names from up to date game data.<br />
<br />
Whoever guessed the next article will be about writing a C2 autopsy tool wins a carrot !<br />
<br />The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-13501019913538840782014-01-23T22:36:00.000+01:002014-02-03T12:06:43.535+01:00Back to more traditionnal automated Norn genealogy using python and graphviz ( Intro )<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEdexGdgUAM-Mx01AtaxbZv3PvEUmJzzOvVKcJkFOqAbRRE8DdH1DSB75q6GFGVm3q5-fzqwVFyepmbVOqcY61kWd38PUoe_Zs49amMMOrTM_GT8vUO-Jp0Zw0tmX9r3PRrpYxYoeUu5gG/s1600/Familytree.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEdexGdgUAM-Mx01AtaxbZv3PvEUmJzzOvVKcJkFOqAbRRE8DdH1DSB75q6GFGVm3q5-fzqwVFyepmbVOqcY61kWd38PUoe_Zs49amMMOrTM_GT8vUO-Jp0Zw0tmX9r3PRrpYxYoeUu5gG/s1600/Familytree.png" height="147" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
We've already had a glimpse at using <a href="http://sheeslostknowledge.blogspot.fr/2014/01/introduction-to-advanced-norn-genealogy_4.html">advanced tools</a> for experiments in Albian genealogy.<br />
Gephi is a nice tool for interactively browsing decently sized datasets on the macro scale, but what about more conventional genealogy tools ?<br />
<br />
In this post I will show you basic use of <a href="http://www.graphviz.org/">graphviz </a>in python to make some more traditional but far more detailed family trees automatically.This will once again be only a short glimpse at graphviz possibilities so we can use it as an useful tool further down the road.<br />
Hopefully it will make you want to add this to your Albian explorer toolbox. <br />
<br />
<a name='more'></a><br />
<br />
In the preceding genealogy article we used the <a href="http://sheeslostknowledge.blogspot.fr/2014/01/parsing-c2-gamelog-files-with-python.html">"Gamelog" file</a> as a source for Norn filliation information.<br />
Building upon <a href="http://sheeslostknowledge.blogspot.fr/2014/01/parsing-c2-histfiles.html">the history file parsing article</a>, we will now be using the History files to get and display more information in a single shot.<br />
<br />
<h2>
But what's graphviz anyway ?</h2>
Graphviz is a library for managing, and generating visualisations of graph data.<br />
We will be manipulating it with python through the pydot wrapper.<br />
<br />
In it's simplest form, a graph is a collection of nodes (elements) and edges (links between nodes).<br />
After installing graphviz and pydot (in that order, it will save you some trouble later on), generating a graph is as simple as doing:<br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">import pydot<br />tree = pydot.Dot(graph_type='digraph')<br /><br />tree.add_edge(pydot.Edge("Mother", "Child 1"))<br />tree.add_edge(pydot.Edge("Mother", "Child 2"))<br />tree.add_edge(pydot.Edge("Father", "Child 1"))<br />tree.add_edge(pydot.Edge("Father", "Child 2"))<br />tree.add_edge(pydot.Edge("GrandMother", "Father"))<br />tree.add_edge(pydot.Edge("GrandFather", "Father"))<br /><br />tree.write_png('Familytree.png')</span></span><br />
<br />
This automatically dumps a "Familytree.png" in the script's current folder :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-K8DSEwBr0Qzn57bLm3GLKFb94h7vWksMpAvhEdWA9hswFZns-4YVQyaTbpcslD97uODkOO73-7xeF0Pn10xOalE72fEEgFOvLDUJcDIoGz2IU9Ubbf9X6YdUT6biY3f61FlFF1B2OVbB/s1600/Familytree.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-K8DSEwBr0Qzn57bLm3GLKFb94h7vWksMpAvhEdWA9hswFZns-4YVQyaTbpcslD97uODkOO73-7xeF0Pn10xOalE72fEEgFOvLDUJcDIoGz2IU9Ubbf9X6YdUT6biY3f61FlFF1B2OVbB/s1600/Familytree.png" height="232" width="320" /> </a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Couldn't have been any easier could it ?(Well, actually I'll admit setting up a full python development environment from scratch just for this to work might be a bit of work the first time :p)<br />
<br />
Don't like PNGs ? replace <span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">tree.write_png('Familytree.png') </span></span>with<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">tree.write_pdf('Familytree.pdf') </span></span>to get a more browsable format with selectable text.<br />
<br />
Using Graphviz boils down to setting up a manageable nodes and edges list, and letting python do it's magic for us.<br />
In this simple example, we've only created edges, while the library automatically updated the nodes list for us whenever an unknown node was specified.<br />
As we will need further control over the nodes shapes, we will have to manage them manually further down the road, but that's not a big deal.<br />
<br />
<h2>
Making graphs from actual Creatures data:</h2>
The next step will be gathering the genealogy information from the game data.<br />
As seen in the preceding article, we will <a href="http://sheeslostknowledge.blogspot.fr/2014/01/parsing-c2-histfiles.html">extract the relevant information</a> from the game's History files.<br />
<br />
We will be building upon our last article's code for parsing history files.<br />
Grab <a href="https://github.com/LoneShee/SLKExamples/blob/master/Historyfileparser.py">Historyfileparser.py</a> and put it in the same folder as your future script.<br />
<br />
This only a slightly modified version of the code shown in the preceding post. It will make importing your whole Norn population information inside your future programs a one-line magic trick such as in :<br />
<br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">import Historyfileparser<br /><br />print Historyfileparser.Norns.keys()</span></span><br />
<br />
<span style="color: lime;"></span><br />
<span style="color: lime;"></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"></span></span>Which will gladly output you a list of all your creatures monikers:<br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> ['8KPO', '6ILB', '4WFW', '2TAV', '8CWN', '7SRX', '6TFX', '7TML', '5CHG', '0BLT']</span></span><br />
<br />
Using that magic, we can now easily make a quick graph of all our Albian population:<br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">import pydot<br />import Historyfileparser<br /><br />tree = pydot.Dot(graph_type='digraph') # Digraph means "oriented links"<br /><br />#print Historyfileparser.Norns["1KTQ"]<br /><br />for moniker in Historyfileparser.Norns.keys():<br /> print moniker,":", Historyfileparser.Norns[moniker]["DadMoniker"],Historyfileparser.Norns[moniker]["MumMoniker"] <br /> tree.add_edge(pydot.Edge(Historyfileparser.Norns[moniker]["MumMoniker"], moniker))<br /><br /> if Historyfileparser.Norns[moniker]["DadMoniker"]!="":<br /> tree.add_edge(pydot.Edge(Historyfileparser.Norns[moniker]["DadMoniker"], moniker))<br /><br />tree.write_png('./ActualFamilytree.png')</span></span><br />
<br />
You can grab the corresponding python file here: <a href="https://github.com/LoneShee/SLKExamples/blob/master/Simplemonikerfamilytree.py">Simplemonikerfamilytree.py</a><br />
<br />
And here is our family tree automatically generated right from the game data :<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5nyglp8RoFn6a_OC7ObI_i4n5Wk_hmwkk2ZQSkbXdCveEQNVGZXIPdr0Xs7kbsCktA85QmjnaSaerMDybes0EQLcSOFNBzypL5V0aLdjYhG3vDR3pUKb8qYuLnhnvk8yLOkQpD0Waxa0j/s1600/ActualFamilytree.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5nyglp8RoFn6a_OC7ObI_i4n5Wk_hmwkk2ZQSkbXdCveEQNVGZXIPdr0Xs7kbsCktA85QmjnaSaerMDybes0EQLcSOFNBzypL5V0aLdjYhG3vDR3pUKb8qYuLnhnvk8yLOkQpD0Waxa0j/s1600/ActualFamilytree.png" height="123" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Remember 4XSW ? He's the result of our <a href="http://sheeslostknowledge.blogspot.fr/2014/01/generating-creatures-2-egg-files-with.html">eggfile generating experiments</a> !</td><td class="tr-caption" style="text-align: center;"></td><td class="tr-caption" style="text-align: center;"></td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
<div style="text-align: center;">
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxenCauyhDD-1ozVaAIBzIKw-9XvFkvINLVbCqbQsXrz_U9DgOwP8WFbw6Mfr0NlCqZY3IW5Y6Se_53nWniIHvYMfWuEMh_vugkRntmJpVwhyphenhyphen0twMqrlbYTUDQl1kJvl1yf7llS0BPT1q0/s1600/2QRW.PNG" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxenCauyhDD-1ozVaAIBzIKw-9XvFkvINLVbCqbQsXrz_U9DgOwP8WFbw6Mfr0NlCqZY3IW5Y6Se_53nWniIHvYMfWuEMh_vugkRntmJpVwhyphenhyphen0twMqrlbYTUDQl1kJvl1yf7llS0BPT1q0/s1600/2QRW.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
</div>
Don't mind the double arrows going from one genome to another.Those are my experiments to check if one could set the same genome twice as the mother's and father's genome when generating an egg.<br />
The answer is that it works in C2 but not in C1.Anyway you shouldn't need to do that, as you can always specify a "0" father genome if you want to make a mono parental child.<br />
<br />
<h2>
Making it cuter</h2>
Alright, so far this makes a lot of work for not much more than we could have made using Gephi, so what's the big deal ?<br />
Graphviz is much more configurable regarding what we can make our nodes look like.<br />
What about something like this?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhF5J8LVN6s6e2e3szoEJUev5hBf5aJyNjG0VfGELGSlPHewwTcmE_LRoXZLKBM6hgqLcG7Dh0df7r35AmIeO5kZ_bgz-p2aBjtbDpJ8_USsaNfwWg-khD31OCmqlG_enTg8xxq3QZqNywA/s1600/FullColoredFamilytree.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhF5J8LVN6s6e2e3szoEJUev5hBf5aJyNjG0VfGELGSlPHewwTcmE_LRoXZLKBM6hgqLcG7Dh0df7r35AmIeO5kZ_bgz-p2aBjtbDpJ8_USsaNfwWg-khD31OCmqlG_enTg8xxq3QZqNywA/s1600/FullColoredFamilytree.png" height="634" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<br />
This was generated using :<br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">import pydot<br />import Historyfileparser<br />import datetime<br /><br />def makelabel(Norn):<br /> label="{"+Norn["Name"]<br /> label+="\n("+moniker+")|{"<br /> label+="Born: "+datetime.datetime.fromtimestamp(Norn["TimeOfBirth"]).strftime('%Y-%m-%d %H:%M:%S')+"|"<br /> if Norn["TimeOfDeath"]!=0:<br /> label+= "Dead: "+datetime.datetime.fromtimestamp(Norn["TimeOfDeath"]).strftime('%Y-%m-%d %H:%M:%S')+"}"<br /> else:<br /> label+="-"+"}"<br /> label+="|{"+Norn["State"]+"}"<br /> label+="}"<br /> return label<br /><br />tree = pydot.Dot(graph_type='digraph',rankdir="LR") # Digraph means "oriented links"<br />Nodes=[]<br /><br />for moniker in Historyfileparser.Norns.keys():<br /> <br /> print moniker,":", Historyfileparser.Norns[moniker]["DadMoniker"],Historyfileparser.Norns[moniker]["MumMoniker"]<br /> lab=makelabel(Historyfileparser.Norns[moniker])<br /> if Historyfileparser.Norns[moniker]["Gender"]=="male":<br /> Nodes.append(pydot.Node(moniker,shape="record",label=lab,style="filled", fillcolor="lightblue"))<br /> else:<br /> Nodes.append(pydot.Node(moniker,shape="record",label=lab,style="filled", fillcolor="pink"))<br /><br /> tree.add_edge(pydot.Edge(Historyfileparser.Norns[moniker]["MumMoniker"], moniker))<br /> if Historyfileparser.Norns[moniker]["DadMoniker"]!="":<br /> tree.add_edge(pydot.Edge(Historyfileparser.Norns[moniker]["DadMoniker"], moniker))<br /><br />for node in Nodes:<br /> tree.add_node(node)<br /><br /><br />tree.write_png('./FullColoredFamilytree.png')</span></span><br />
<br />
<br />
This was barely more complicated, we only added a bit of formatting to the cells. <br />
You could use any of the available information and present it in any shape you like.<br />
The label shape specification supports some basic HTML inspired syntax so you can design your nodes as HTML tables containing arbitrarily formatted text and images. <br />
I had to arrange the tree vertically so it fits on the page, but here's a more natural view (sorry about the size issues):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT4Awq1VLOo9MrADjceXihKrHfpSfS2diRhxBjnzMAQZOqUk3ZXh89GNnzxoFvRdUmm3Z9wwrO5ff9wusLRXpw7U9OBVHvhjscN_GbRk7n-69zgoiqQuTVOAgtd3u2ZQkltE10G4GO5msz/s1600/FullColoredFamilytree.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT4Awq1VLOo9MrADjceXihKrHfpSfS2diRhxBjnzMAQZOqUk3ZXh89GNnzxoFvRdUmm3Z9wwrO5ff9wusLRXpw7U9OBVHvhjscN_GbRk7n-69zgoiqQuTVOAgtd3u2ZQkltE10G4GO5msz/s1600/FullColoredFamilytree.png" height="57" width="640" /></a></div>
<span style="background-color: yellow;"><br /></span>
<br />
You see those white bubbles ? Those are nodes we didn't explicitly create from Histfiles, meaning that no Norn with that genome ever walked our Albia, but rather these were merely mentioned as a reference in a Norn's parent information.Pretty convenient.<br />
<br />
By using the <a href="https://github.com/LoneShee/SLKExamples/blob/master/C2Genealogy_Example.py">following script</a>, we can further improve the model and cram some more data in our nodes,making them a more complete and usable genealogy tool:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYAkveaUcVPWCsUpsOo2RE68F26bpQ5iajE-9VHoWpfdLtnxqX6Y8SB18bJsTulQogUSQLjLavn-IrMlDeCRaj8PIl9OamyCQ6SBlTJSYHhik-Ghj9SqyS0cW8o9PsMBeuJVJkcHb6Mu-B/s1600/cutegraph.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYAkveaUcVPWCsUpsOo2RE68F26bpQ5iajE-9VHoWpfdLtnxqX6Y8SB18bJsTulQogUSQLjLavn-IrMlDeCRaj8PIl9OamyCQ6SBlTJSYHhik-Ghj9SqyS0cW8o9PsMBeuJVJkcHb6Mu-B/s1600/cutegraph.png" height="275" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Each node contains the following information: sex as background color,
living/dead state as the node's outline color, genus as the datum background, all of this along with the readily identifiable textual information.</td></tr>
</tbody></table>
<div style="text-align: center;">
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzejpmBZmGik8gPzDcQd7mBXN3qm44eOS8s0SUKSJpQbMpC3y4_IWvgPGygnPBWj1kU_mJ_fzmdf3uxHRuJlx7FiUTp50GfmQFsi2T1qZ7pHiP1rX_vGOZwtLq7jMKx8EPR2PKl96x23sy/s1600/2.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzejpmBZmGik8gPzDcQd7mBXN3qm44eOS8s0SUKSJpQbMpC3y4_IWvgPGygnPBWj1kU_mJ_fzmdf3uxHRuJlx7FiUTp50GfmQFsi2T1qZ7pHiP1rX_vGOZwtLq7jMKx8EPR2PKl96x23sy/s1600/2.PNG" height="159" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Red outline is a dead creature, green is a living one and yellow an exported one.Grendels have green date backround, ettins light yellow, and Norns light brown ones.</td><td class="tr-caption" style="text-align: center;"><br /></td><td class="tr-caption" style="text-align: center;"><br /></td><td class="tr-caption" style="text-align: center;"></td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
</div>
<div style="text-align: left;">
<br />
For now I've cheated a bit and am using manually extracted images as the source for creatures pics, but after I show you in an upcoming article how to parse and extract information directly from .s16 files, we will be able to extract those automagically from the photo album files as well.</div>
<br />
Isn't it nice to have all the hard data-gathering and formatting work done for us automatically form game data?<br />
No more inaccurate or outdated family trees :) ,it only takes a click to get fully up to date information.And you can run that on as many worlds you want, as many times you want.<br />
You could even schedule regular snapshots of your Norn's population or wolfing runs for later review if you're so inclined.<br />
They're also graphviz components for rendering graphviz data directly inside your web site.<br />
You could even sahre a realtime tree of your Norn population with your visitors.(The Google API features an interface for that, but it's implementation was incomplete last time I checked) <br />
<br />
If you're not impressed with graphviz visualisations, you could always dump the raw graph data in a <a href="http://www.graphviz.org/doc/info/output.html">variety of text formats</a> to be later imported into your favorite genealogy tool.<br />
<br />
Here's a last screenshot of the Wolfing run we've seen mapped in the Gephi post:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigS1Ci17mqRtXOW6f9C5xhwli9zKM6EIfKwGqKNMpkN1iirlaKu7NfI6moW4vawIp36-yOOo0thSgIbf8VEryy7vc61mABo14g2jfTciiM8QtjUkKbPp-955Ms4wJyXpv5gr5Gauy5FjNm/s1600/Familytree.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigS1Ci17mqRtXOW6f9C5xhwli9zKM6EIfKwGqKNMpkN1iirlaKu7NfI6moW4vawIp36-yOOo0thSgIbf8VEryy7vc61mABo14g2jfTciiM8QtjUkKbPp-955Ms4wJyXpv5gr5Gauy5FjNm/s1600/Familytree.png" height="165" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">"Dot" is a hierarchy oriented renderer, making it particularly suitable for drawing family trees.Without further intervention from us, it aligned Norns by generations.</td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUbPoT5Kgmt3n8fcdlW8IhD1v30NOia4FxGYMufbTzA9au7h3N5eB3F1D4epyYojAJM2bS1qF1Kvn1CvBWSd5nIO8FSJv23aa33VitnwuQZhV6xp9nqHp6dQD2ADWgIeuhASlEdA8Yb-Xp/s1600/neat.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUbPoT5Kgmt3n8fcdlW8IhD1v30NOia4FxGYMufbTzA9au7h3N5eB3F1D4epyYojAJM2bS1qF1Kvn1CvBWSd5nIO8FSJv23aa33VitnwuQZhV6xp9nqHp6dQD2ADWgIeuhASlEdA8Yb-Xp/s1600/neat.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Close up of the graph, showing the tree conveniently ordered by generations</td></tr>
</tbody></table>
<br />
<br />
<h2>
Going further</h2>
Graphviz is a very versatile tool and can be used to represent any kind of graph data in any shape you want.<br />
We used it here for genealogy, and as a pretext to reuse one of our preceding file parsing code to illustrate it's usefulness, but there's more you could do:<br />
<ul>
<li>Use it to draw your world's timeline from the GameLog file</li>
<li>Use it to automatically draw a map of all chemicals and reactions happening inside a Norn right from it's genome file.</li>
<li>Use it to visually map genomes by gene types or organs for easier browsing</li>
<li>Use it to produce visual diffs between 2 Norn's genomes (show the common part in white, along with added/modified/missing genes color coded by difference type)</li>
<li>Use it to visualise all scripts of the game scriptorium in a giant map, so you don't waste time manually browsing through vast wastelands of empty scripts by ID.</li>
<li>Use it to map a cob's components and dependencies for quick anlysis (scripts, images,effects...)</li>
<li>Your idea here ? </li>
</ul>
<br />
All of these will be covered in upcoming articles once the corresponding pre-requisites get their own articles.<br />
I'm particularly excited about the ability to automatically map out a Norn's biochemistry without having to painfully mess around in a genetics kit to find every single place where a given chemical was used, but there's a couple things I must show you first before we get to that (reversing and parsing the C1 genome files and c2 allchemicals.str files...) do i smell upcoming articles?<br />
<h2>
References </h2>
Graphviz is a very powerful tool, and you could potentially arrange the nodes and graph in any shape you want, and containing any information you like.<br />
Obviously, I can't cover all of that here, and you'll have to look up the eye candy stuff by yourself (or wait for my next updates)<br />
<br />
So here are some links if you want to dig further down on this topic:<br />
<ul>
<li>The <a href="http://www.graphviz.org/">graphviz site</a></li>
<li>A <a href="http://pythonhaven.wordpress.com/2009/12/09/generating_graphs_with_pydot/">quick tutorial</a> among many other about basic graphviz usage and customisation</li>
<li>A <a href="http://www.graphviz.org/pdf/dotguide.pdf">complete guide</a> on all you need to know about the "Dot" format we used throughout this post to describe our graphs.If you only could read one thing, read this one.It has usage example for various layouts, timelines, node shaping...</li>
<li><a href="http://graphviz-dev.appspot.com/">One of many online graphviz test apps</a> so you can mess around with designing your graph manually before coverting everyhing to python code.</li>
</ul>
<br />
Let me know if you'd like me to give more details about any of this.<br />
Happy graphing ! <br />
<span style="color: lime;"></span>The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-35892562618328143332014-01-22T00:26:00.000+01:002014-09-08T22:10:53.538+02:00Parsing C2 histfilesOnce again, a quick filler post about parsing a random creatures file format.<br />
<br />
This time we will be investigating the Creatures 2 "History file" format.<br />
<br />
This one is also already <a href="http://www.gamewaredevelopment.com/cdn/CDN_more.php?CDN_article_id=95#history">documented online</a>, but being able to parse it can allow us to extract some interesting data.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjYJV1I2Kf9hTlU1DUf3tZCR9EjsYwzhhJnELOMUpyNiLSGoAaAjTqZa-x7R5yKVAjiN0Dg_bxdh4xQv7nCfZQVeWmWpiA1UrXwQAZ6sAlE1i75hVodiB2bvrRlCa94DghtXIZjO0HfWi-/s1600/Histfiles.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjYJV1I2Kf9hTlU1DUf3tZCR9EjsYwzhhJnELOMUpyNiLSGoAaAjTqZa-x7R5yKVAjiN0Dg_bxdh4xQv7nCfZQVeWmWpiA1UrXwQAZ6sAlE1i75hVodiB2bvrRlCa94DghtXIZjO0HfWi-/s1600/Histfiles.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">I guess this post needed at least one picture</td></tr>
</tbody></table>
<br />
<a name='more'></a><br />
<br />
<h2>
Where?</h2>
The History files are found in your C2 game directory, inside the adequately named "History" folder.<br />
<br />
In there you will find :<br />
<ul>
<li>The <a href="http://sheeslostknowledge.blogspot.fr/2014/01/parsing-c2-gamelog-files-with-python.html">GameLog file</a> we've already learnt to parse. </li>
<li>A series of "Photo_XXXX.s16" files. These are your C2 Norns photo albums, where XXXX is each Norns moniker.These are standard .s16 files you can browse with one of the many available tools.We'll <a href="http://sheeslostknowledge.blogspot.fr/2014/02/parsing-creatures-2-s16-files.html">learn to parse and manipulate them</a> in an upcoming article.</li>
<li>A series of "cr_XXXX" files, these are the History Files we are interested in this time.</li>
<li>Optionally a set of folders, one by alternative world you played using the C2 world switcher.They contain all of the preceding items for each world. </li>
</ul>
For each Norn that took an active part in your game, you can find a "cr_XXXX" file in the History folder where XXXX is once again the Norn's moniker.<br />
<br />
<h2>
What? </h2>
Here's the information you can get out of this file, along with the format information :<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">Type Meaning <span style="color: lime;">Explanation</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;">4 bytes Moniker <span style="color: lime;">The Norn's Moniker</span> <br />CString Name <span style="color: lime;">The Norn's name if any</span> <br />4 bytes MumMoniker <span style="color: lime;">The Norn's Mother Moniker </span><br />CString MumName <span style="color: lime;">The Norn's Mother's name if any</span><br />4 bytes DadMoniker <span style="color: lime;">The Norn's Father Moniker (\x00\x00\x00\x00 if none, but always present)</span><br />CString DadName <span style="color: lime;">The Norn's Father's name if any</span><br />CString Birthday <span style="color: lime;">A litteral representation of the Norns birth date ( ex :22:59 Jan 10 2014 )</span><br />CString Birthplace <span style="color: lime;">The Norn's birthplace</span><br />CString OwnerName <span style="color: lime;">Owner info as set in the owner kit.</span> <br />CString OwnerURL <span style="color: lime;">Owner info as set in the owner kit.</span><br />CString OwnerNotes <span style="color: lime;">Owner info as set in the owner kit.</span><br />CString OwnerEMail <span style="color: lime;">Owner info as set in the owner kit.</span><br />1 LONG State <span style="color: lime;">The Norn's status : 0=alive, 1=dead, 2=exported</span><br />1 LONG Gender <span style="color: lime;">The Norn's gender: 1=male, 2=female</span><br />1 LONG Age <span style="color: lime;">The Norn's age ? Seems to be 0 for all my Norns</span><br />CString Epitaph <span style="color: lime;">The Norn's epitaph if any</span><br />1 LONG GravePhotoIndex <span style="color: lime;">An index in the Norns photo album for finding the Grave picture ( 4294967295 by default) </span><br />1 LONG TimeOfDeath <span style="color: lime;">Time of death, expressed as an Unix timestamp </span><br />1 LONG TimeOfBirth <span style="color: lime;">Time of birth,expressed as an Unix timestamp</span><br />1 LONG TimeOfAdolescence <span style="color: lime;">Time of reaching adolescence,expressed as an Unix timestamp </span> <br />1 LONG DeathRegistered <span style="color: lime;">Self explanatory, 0=no,1=yes</span><br />1 LONG Genus <span style="color: lime;">The Creatures kind ( yes, grendels and ettins also have histfiles!) </span><span style="color: lime;">1=norn, 2=grendel, 3=ettin</span><br />1 LONG LifeStage <span style="color: lime;">The 0-6 Norn's life stage, as always: <br />0=Baby,1=Child,2=Adolescent,3=Youth,4=Adult,5=Old,6=Senile </span><br />256 bytes ChemsAtDeath <span style="color: lime;">A 256 bytes array, containing the 256 chemical levels inside the Norn at death</span><br />9 LONGs Padding <span style="color: lime;">Unused, Must be zeroes</span> </span><br />
<br />
<br />
<h2>
Potential uses:</h2>
Well, that looks like a one stop file for a lot of interesting information !<br />
<br />
What could we do with all that ?<br />
<ul>
<li>Obviously this looks like an appropriate place for quickly <a href="http://sheeslostknowledge.blogspot.fr/2014/01/introduction-to-advanced-norn-genealogy_4.html">extracting a Norns family details</a> such as mother and father's monikers and names</li>
<li>Scanning the whole fileset will quickly help you identifying which Norns are still alive, dead or have been exported.This is useful if you doubt about still having a copy of a given Norn.</li>
<li>You could finally edit that misspelled epitaph on your favorite Norn's grave.Yes, this does work! The history files are the ones containing the actual ingame grave information.And it works for changing pictures too.Nothing is set in stone anymore ;)</li>
<li>You could perform Norn autopsy by printing out and studying the chemicals present in it's body at death. This would have an advantage over existing tools such as cred32 in at least 3 ways : Works with C2, Has a stable and fixed record of the chemicals that won't change, can be performed long after death, even after a Norn's body has disappeared from the world.We will be writing a custom tool to do just that in an <a href="http://sheeslostknowledge.blogspot.fr/2014/01/finally-creatures-2-norn-autopsy-tool.html">upcoming article</a>, meanwhile if you're into Norn autopsies, I suggest you take a look at <a href="http://discoveralbia.blogspot.fr/2013/02/the-norn-autopsy-feature-of-cred32.html">this great "Discover Albia" post</a>. </li>
<li>Not directly related, but by browsing the photoalbum files, you can finally recover all of the pictures ever taken of all your deceased Norns.This is good to have as once they're dead, the game only lets you see one last picture forever.</li>
</ul>
<h2>
Additional "Cstring" info: </h2>
Right before we get to the actual demo, just a word on the "Cstring" type used by some of these entries.<br />
<br />
Contrary to what one might think, what the CDN calls "Cstrings" are not the C language '\0' terminated strings.But rather strings prefixed with length information.<br />
They take two forms:<br />
If the string is shorter than 256 characters, it is read as<br />
<"1 byte" length> <"length bytes" actual string><br />
<br />
If you read out the length byte and find out it is "255", then you'll have to discard that byte, and read an additional "Word" ( 2 bytes).<br />
That means the string is longer than 256 bytes and that "Word" gives you the string length, as in :<br />
<"1 '225'byte"><"1 Word" length><"length bytes" actual string><br />
<br />
<h2>
The script: </h2>
As usual here is a small python script illustrating how to parse the history file format.<br />
( this one has to be run from your creatures directory ) <br />
Oh, and by the way, may the purists pardon my highly unpythonic use of the language, but I'm trying to keep things simple and readable for everybody there. I know this code could be made much shorter and reusable.<br />
The complete file is available at <a href="https://github.com/LoneShee/SLKExamples/blob/master/Parsehistfiles_example.py">Parsehistfiles_example.py</a>. <br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">import os<br />import struct<br /><br /><br />def readbyte( readfromfile ):<br /> return struct.unpack("B",readfromfile.read(1))[0]<br /><br />def readLong( readfromfile ):<br /> return struct.unpack("L",readfromfile.read(struct.calcsize("L")))[0]<br /><br />def readCstring (readfromfile):<br /> """<br /> CStrings are strings which have length data linked with them. The format<br /> is flexible and they are read as follows:<br /><br /> READ BYTE Length<br /> If Length=255 then READ WORD Length<br /> READ Char[Length] into String<br /> """<br /> strlength = struct.unpack("B", readfromfile.read(1))[0]<br /> if strlength == 0xff:<br /> strlength = struct.unpack("H", readfromfile.read(2))[0]<br /> return readfromfile.read(strlength)<br /><br />files=os.listdir(".")<br /><br />Norns={}<br />for histfile in files:<br /> if histfile[0:2]=="cr":<br /> Norns[histfile[3:]]={}<br /> fic=open(histfile,"rb")<br /><br /> Moniker=fic.read(4)<br /> <br /> Name=readCstring(fic)<br /> Norns[Moniker]["Name"]=Name<br /><br /> MumMoniker=fic.read(4)<br /> Norns[Moniker]["MumMoniker"]=MumMoniker<br /><br /> MomName=readCstring(fic)<br /> Norns[Moniker]["MomName"]=MomName<br /><br /> DadMoniker=fic.read(4)<br /> Norns[Moniker]["DadMoniker"]=DadMoniker<br /><br /> DadName=readCstring(fic)<br /> Norns[Moniker]["DadName"]=DadName<br /><br /> BirthDate=readCstring(fic)<br /> Norns[Moniker]["BirthDate"]=BirthDate<br /><br /> BirthPlace=readCstring(fic)<br /> Norns[Moniker]["BirthPlace"]=BirthPlace<br /><br /> OwnerName=readCstring(fic)<br /> Norns[Moniker]["OwnerName"]=OwnerName<br /><br /> OwnerURL=readCstring(fic)<br /> Norns[Moniker]["OwnerURL"]=OwnerURL<br /> <br /> OwnerNotes=readCstring(fic)<br /> Norns[Moniker]["OwnerNotes"]=OwnerNotes<br /><br /> OwnerMail=readCstring(fic)<br /> Norns[Moniker]["OwnerMail"]=OwnerMail<br /><br /> State=readLong(fic)<br /> State=["alive","dead","exported"][State] #Isn't python awesome ?<br /> Norns[Moniker]["State"]=State<br /><br /> Gender=readLong(fic)<br /> Gender=[None,"male","female"][Gender] <br /> Norns[Moniker]["Gender"]=Gender<br /><br /> Age=readLong(fic)<br /> Norns[Moniker]["Age"]=Age<br /><br /> Epitaph=readCstring(fic)<br /> Norns[Moniker]["Epitaph"]=Epitaph<br /><br /> GravePhotoIndex=readLong(fic)<br /> Norns[Moniker]["GravePhotoIndex"]=GravePhotoIndex<br /><br /> TimeOfDeath=readLong(fic)<br /> Norns[Moniker]["TimeOfDeath"]=TimeOfDeath<br /><br /> TimeOfBirth=readLong(fic)<br /> Norns[Moniker]["TimeOfBirth"]=TimeOfBirth<br /><br /> TimeOfAdolescence=readLong(fic) # Yay! Kisspoping time !<br /> Norns[Moniker]["TimeOfAdolescence"]=TimeOfAdolescence<br /><br /> DeathRegistered=readLong(fic)<br /> DeathRegistered=["no","yes"][DeathRegistered] <br /> Norns[Moniker]["DeathRegistered"]=DeathRegistered<br /><br /> Genus=readLong(fic)<br /> Genus=[None,"Norn","Grendel","Ettin"][Genus] <br /> Norns[Moniker]["Genus"]=Genus<br /><br /> Lifestage=readLong(fic)<br /> Lifestage=["Baby","Child","Adolescent","Youth","Adult","Old","Senile"][Lifestage] <br /> Norns[Moniker]["Lifestage"]=Lifestage<br /><br /> ChemicalsAtDeath=fic.read(256)<br /> Norns[Moniker]["ChemicalsAtDeath"]=ChemicalsAtDeath<br /><br />print "Available monikers:"<br />for norn in Norns:<br /> print norn,":",Norns[norn]["State"]<br /><br />who = raw_input("Enter a moniker: ")<br /><br />for key in Norns[who]:<br /> if key != "ChemicalsAtDeath":<br /> print key,":",Norns[who][key]<br /> elif Norns[who]["State"]=="dead":<br /> print "Chemicals at death:"<br /> for chem in Norns[who]["ChemicalsAtDeath"]: print ord(chem),<br /> else:<br /> print "The creature is not dead!"<br /> </span></span><br />
If we run the script we get :<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">Available monikers:<br />1KTQ : alive<br />4YJH : alive<br />5KPD : exported<br />2QRW : alive<br />8KEI : alive<br />4KOV : alive<br />4XSW : alive<br />0FSF : alive<br />4VTI : alive<br />2MYK : dead<br />3LON : alive<br />4BJO : alive<br />Enter a moniker: <span style="color: red;">2MYK</span><br />DeathRegistered : yes<br />State : dead<br />OwnerURL : <br />TimeOfBirth : 1388689204<br />BirthDate : 20:00 Jan 02 2014<br />DadMoniker : 4YJH</span><br />
<span style="font-family: "Courier New",Courier,monospace;">MomName : <br />OwnerName : <br />MumMoniker : test<br />Epitaph : Drowned a 4th time in a row while unattended.<br />TimeOfDeath : 1389628745<br />Name : <pas de nom><br />Gender : female<br />Age : 0<br />DadName : <br />Genus : Norn<br />OwnerNotes : <br />BirthPlace : The birthplace<br />OwnerMail : <br />Lifestage : Child<br />TimeOfAdolescence : 486834176<br />GravePhotoIndex : 4294967295<br />Chemicals at death:<br />0 0 116 250 0 155 139 86 20 0 19 5 0 0 0 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 248 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 161 84 68 1 192 0 0 75 216 188 1 0 34 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 6 1 254 0 0 0 0 0 0 0 0 0 0 0 0 137 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 91 98 0 104 91 0 0 0 0 0 0 0 0 0 0 0 </span><br />
<br />
<br />
After another upcoming post on reversing and parsing the C2 alchemicals.str file, we will wrap all this up by designing an usable C2 autopsy tool that will match meaningful chemicals names to this garbage :)<br />
<br />
<br />The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-67137687540233491492014-01-20T19:43:00.000+01:002014-01-25T15:35:20.533+01:00Designing farting norns (Tutorial)<br />
Many colored alternative breeds exist for all of the creatures games.<br />
<br />
In this tutorial I will show you how to design a new breed for C1.<br />
But not one that involves making new sprites for new colored or punk Norns, but rather one that implements new Norn behaviours and possibilities.<br />
Using those techniques one could add loads of interesting behaviours to Norns such as :<br />
<ul>
<li>Adding a kicking stance and associated behaviours to fight off Grendel more efficiently</li>
<li>Making Norns that can reinvigorate and heal by resorting to meditation</li>
<li>Enabling actual telekinesis in Norns ( yes, this IS possible with some work )</li>
<li>Making jumping Norns</li>
<li>Mimicking more realistic life behaviour ( digestion, elimination ... )</li>
<li>...</li>
</ul>
But this time we will be:<br />
<br />
<h2>
Making Farting Norns:<a name='more'></a></h2>
Why would anyone want to do that ? Well, I believe we should keep some humor while playing God if we want to be any successful at it.<br />
Also it is an easy way to teach beginners the basis of new breed designs, without resorting to the most common and painful approach of defining a new breed by making new Norns appearances. <br />
<br />
This tutorial will take you through all the necessary steps to give your Norns the ability to fart, not just as a game gimmick, but as the real simulation of a noisy digestive process.<br />
<br />
<h2>
Acquiring the material:</h2>
The first significant step in designing farting Norns is finding one (or more) suitable sound.<br />
Find one that suits your needs, then rename it to a 4 character name (this is mandatory for all C1 files).I chose to name it "fart.wav"<br />
Put it inside your game's "Sounds" folder.<br />
<br />
You can now test it by running a game and executing the following CAOS command using your <a href="http://double.co.nz/creatures/programs/CCmdLine_exe.zip">favorite tool. </a><br />
<br />
<div style="margin-bottom: 0cm;">
<span style="color: #ffe599;"> snde fart</span></div>
<div style="margin-bottom: 0cm;">
<br /></div>
Note that injecting the sound from the external tool will take focus away from the game and most likely mute it.You could also test the sound by looping it with the command:<br />
<br />
<span style="color: #ffe599;"> sndl fart</span><br />
<br />
and then stopping it with the command:<br />
<br />
<span style="color: #ffe599;"> stpc</span><br />
<br />
This is just to make sure you picked a sound file in a format that the game can read and play.<br />
Did it work ? Great, let's move on:<br />
<br />
<h2>
Writing a first farting script :</h2>
As any other ingame action, our actual farting action will be a CAOS script that will be ran at the (un)appropriate occasions.<br />
Let's begin with something simple for testing, we will be expanding it later.<br />
<br />
<span style="color: #ffe599;">sndq fart 5,sndq gig2 10</span><br />
<br />
This will make a Norn play a farting sound, followed by a giggle.<br />
Keep in mind the two sndq functions will be executed nearly at the same time, the second one won't wait for the first to end. The delay values must be set accordingly if you want a slight delay between both sounds. <br />
<br />
<h2>
Defining a new "Involuntary Action" :</h2>
There's a couple free slots in the various games where one could implement "Involuntary actions".<br />
These are actions that a Norn doesn't decide to trigger, but rather that fire off automatically given certain conditions ( Giving birth, sneezing or dieing are all involuntary actions ).<br />
<br />
You can look for the existing involuntary actions using a CAOS console or a scriptorium browser.<br />
( An accurate reference of C1 involuntary actions is available in the C1 SDK pdf file. )<br />
<br />
We will store our new script using the classifier : 4 0 0 71 ( Creatures -> All creatures -> All sexes -> Involuntary action 7 ) , this slot should be free both in C1 and C2.<br />
<br />
You can retrieve a script from any slot by using :<br />
<br />
<span style="color: #ffe599;">dde: scrp 4 0 0 71</span><br />
<br />
To install our new script in the 4 0 0 71 slot , we can use :<br />
<br />
<span style="color: #ffe599;"> scrx 4 0 0 71,scrp 4 0 0 71,sndq fart 5,sndq gig2 10,endm </span><br />
<br />
( Be careful as this also removes any script precedently available in this slot, don't overwrite any default game script!Well...should you want to mess around, 4 0 0 72 is the death script, see what you can make with that ;)<br />
<br />
You can then test that your script is correctly installed by running :<br />
<br />
<span style="color: #ffe599;">dde: scrp 4 0 0 71</span><br />
<br />
<br />
From on now, your world has a new involuntary action available for all creatures.<br />
( Keep in mind this script will disappear should you reset to a virgin world.We will later see how to install it in the default "Eden.sfc" world that is used as a template for resets so you'll never have to worry about that again.)<br />
<br />
<h2>
</h2>
<h2>
Making a new farting Norn genome :</h2>
Now the involuntary action has been installed in the world, we still need Norns designed to actually use it.<br />
I chose to base my Farting Norn breed on the Purple mountain Norns race as they offer some interesting characteristics.<br />
<br />
Fire up the C1 genetics kit, and navigate to the Biochemistry tab.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVTOjoVG_ytNaAAUzz5-GYRLgxouBM0n6nv5W9Q6nn2rdRfOX-qOzsIsjfTCetHtOLXOFsbC4IbhnV1cKG5ADQxo98-2MpCbegr31Ax8VdXypCl-JJvFO8bHpHVG7QpeBgC7UfS-xwpVbC/s1600/c1chems.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVTOjoVG_ytNaAAUzz5-GYRLgxouBM0n6nv5W9Q6nn2rdRfOX-qOzsIsjfTCetHtOLXOFsbC4IbhnV1cKG5ADQxo98-2MpCbegr31Ax8VdXypCl-JJvFO8bHpHVG7QpeBgC7UfS-xwpVbC/s1600/c1chems.PNG" height="400" width="382" /></a> </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Pick a free slot for a new chemical ( I chose 73, but don't know if this conflicts with any known other creatures breed )</div>
<div class="separator" style="clear: both; text-align: left;">
Name the New chemical "Gas (Fart)".</div>
<div class="separator" style="clear: both; text-align: left;">
This will be the chemical accumulating inside the Norn's body, and triggering the involuntary action when a given threshold is reached.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
You will now need to Install the Chemical list in game ( so the new chemical shows in monitoring and injection applets with the new name )</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOrPk8pyNrETHVsIa0YirS9QG3chx8sY9wl4S0Q_LicvaiWj_R-YiBodMxDS_uKE1vmRMGlXkhbur-Hfqjw16232W6LYpdyZZlyix0RTH9UCoWztWKje5gEXSdGRoFAyDFrpGIIx-qBwuQ/s1600/installchem.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOrPk8pyNrETHVsIa0YirS9QG3chx8sY9wl4S0Q_LicvaiWj_R-YiBodMxDS_uKE1vmRMGlXkhbur-Hfqjw16232W6LYpdyZZlyix0RTH9UCoWztWKje5gEXSdGRoFAyDFrpGIIx-qBwuQ/s1600/installchem.PNG" height="400" width="383" /></a> </div>
<br />
<br />
You can now run the game, and find the new chemical available:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-at0OHKKVv_jzHCwCIm61bUM2GwyVI1vPJQRhnDSBn4W1-rP_rAP_RNW5yIyzKaJe9nUo4SQAgU0a_yPWfBJAlno-dHurLEeSHGeWIhc6SVx09fP1JykctQntXWdFbYZ0guG8a3jONWzA/s1600/fartmonitor.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-at0OHKKVv_jzHCwCIm61bUM2GwyVI1vPJQRhnDSBn4W1-rP_rAP_RNW5yIyzKaJe9nUo4SQAgU0a_yPWfBJAlno-dHurLEeSHGeWIhc6SVx09fP1JykctQntXWdFbYZ0guG8a3jONWzA/s1600/fartmonitor.PNG" height="296" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Close the game for now, and return to the Genetics Kit.</div>
<div class="separator" style="clear: both; text-align: left;">
Open your base Genome, I will be using 0XER ( Aaron, the Purple mountain Norn )</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Click on add a new gene, and create a new receptor gene.</div>
<div class="separator" style="clear: both; text-align: left;">
Configure it as such:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwL1E6D8d4DBYn8Jr1S-Y60e5D4MJZdzyHX6itSw3YFz_7r4YZgHrjU1tu38moUCmMeRig7nnSUZqWyAMLfxtr8DBMLNA1APj66DaVL55fgsG9zg46JCaX_rzUscK1peq5O6x9aJ7LFgY8/s1600/Fartreceptor.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwL1E6D8d4DBYn8Jr1S-Y60e5D4MJZdzyHX6itSw3YFz_7r4YZgHrjU1tu38moUCmMeRig7nnSUZqWyAMLfxtr8DBMLNA1APj66DaVL55fgsG9zg46JCaX_rzUscK1peq5O6x9aJ7LFgY8/s1600/Fartreceptor.PNG" height="320" width="286" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
This means that whenever the chemical 73 ( Gas ) level in the Norn will get over the Threshold value, the involuntary action 7 will be triggered.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Save your genome as Fart.gen, and inject a New Norn with this genome inside the game.</div>
<div class="separator" style="clear: both; text-align: left;">
( Use the "Export" Tab in the Genetics Kit )</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h2 class="separator" style="clear: both; text-align: left;">
Testing things so far: </h2>
<div class="separator" style="clear: both; text-align: left;">
Hatch the newly imported Norn, and go to the science kit.</div>
<div class="separator" style="clear: both; text-align: left;">
Set a graph to Monitor Gas which should be 0 for now.</div>
<div class="separator" style="clear: both; text-align: left;">
Using a Caos injection tool ( such as the one available on the "Export" tab in the genetics kit ), you can use the following commands to monitor the Gas chemical level or to inject some inside the Norn:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #ffe599;">dde: putv chem 73</span><span style="color: #b6d7a8;"> # Get a Norn's Gas level</span></span></div>
<div style="margin-bottom: 0cm;">
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #ffe599;">chem 73 30 </span> <span style="color: #b6d7a8;"># Add 30 Gas to the Norns body</span></span></div>
<br />
<div style="margin-bottom: 0cm;">
<br />
You can notice that whenever you inject Gas inside the Norn, the monitoring graph shows it.</div>
<div style="margin-bottom: 0cm;">
When the concentration of the 73 chemical reaches the threshold configured inside the genome, the Norn should start farting uncontrollably.Proving the script works as intended.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicOG3iVD_aJ7D7ttlt789skAciWlZhqp9gpRIk8MGYE26Vn4k7z6MFnaUhU3ZdcHEVIa3upXa2DGutbH5qT8mdJrqNp5MDaRt6p7_hcH4Dk03VhXVz-JGHJRaAApzW9BpdhOrhuCF0IVZt/s1600/Fart+increase.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicOG3iVD_aJ7D7ttlt789skAciWlZhqp9gpRIk8MGYE26Vn4k7z6MFnaUhU3ZdcHEVIa3upXa2DGutbH5qT8mdJrqNp5MDaRt6p7_hcH4Dk03VhXVz-JGHJRaAApzW9BpdhOrhuCF0IVZt/s1600/Fart+increase.PNG" height="223" width="320" /></a></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<h2 class="separator" style="clear: both; text-align: left;">
Adding the natural processes:</h2>
<div class="separator" style="clear: both; text-align: left;">
For now our Norn only farts when manually injected with the chemical, which has no natural occurrence in the game yet.</div>
<div class="separator" style="clear: both; text-align: left;">
Also more problematic, the gas levels never decrease, meaning that once the farting threshold is reached, your Norn won't ever stop farting.Not exactly what we want.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
In the Creatures series, you can add all sorts of chemicals to your Norn's blood stream ( via cobs or CAOS commands ), but the chosen model doesn't give you any way of directly REMOVING one from your creatures.This makes sense regarding the overall cohesion of the simulation.</div>
<div class="separator" style="clear: both; text-align: left;">
After all, things are similar in real life aren't they ?</div>
<div class="separator" style="clear: both; text-align: left;">
To destroy the Gas chemical, we will need to add a second chemical.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Let's make it Number 74, and call it "Fardecrase".Do so in the genetics kit:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOattbTLgROmioWWjduJeytEwtVs_ZCnnq8X_uviLxevvjtwrDfrDYVILzHuun5eF89PnVHoXcaTShmwDIyISxGZviGcs5Hqd7qePUqm55A4Cjy7dwF3QTYXzyoTmNoHTNFPpA6dpdkhMj/s1600/fardecrase.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOattbTLgROmioWWjduJeytEwtVs_ZCnnq8X_uviLxevvjtwrDfrDYVILzHuun5eF89PnVHoXcaTShmwDIyISxGZviGcs5Hqd7qePUqm55A4Cjy7dwF3QTYXzyoTmNoHTNFPpA6dpdkhMj/s1600/fardecrase.PNG" height="400" width="382" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Don't forget to reinstall the new chemicals list.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
We will now need to add a new gene inside the Norn, defining the chemical reaction by which Fardecrase will destroy the Gas chemical.</div>
<div class="separator" style="clear: both; text-align: left;">
Make it a Chemical reaction gene and configure it as follows:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNFPquanNHdwJ5ex1Bo2mQc262IXApAu96lqogd2RjhydEA1nt96GqtLDcPmJm_89QFgAmbbuC7itHqAhJJybEQdy5GAqo3cNzx7on-AfTu2tuVUEpMJwH26qiBagNZMhDqPOhe2FwOhJb/s1600/fart+reaction.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNFPquanNHdwJ5ex1Bo2mQc262IXApAu96lqogd2RjhydEA1nt96GqtLDcPmJm_89QFgAmbbuC7itHqAhJJybEQdy5GAqo3cNzx7on-AfTu2tuVUEpMJwH26qiBagNZMhDqPOhe2FwOhJb/s1600/fart+reaction.PNG" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
This reaction basically means that 2 units of Fardecrase combine with as much Gas units in a pretty fast reaction, and that both chemicals are destroyed in the process.</div>
<div class="separator" style="clear: both; text-align: left;">
If injected with Fardecrase, the Norns Gas levels will now quickly drop.</div>
<div class="separator" style="clear: both; text-align: left;">
We will use this as a means to simulate err...pressure relief.</div>
<div class="separator" style="clear: both; text-align: left;">
For this to work we will tune our farting script, so farting now generates Fardecrase, effectively eliminating gas from the Norn's system.</div>
<div class="separator" style="clear: both; text-align: left;">
Install the new version of the script :</div>
<div class="separator" style="clear: both; text-align: left;">
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;"> scrx 4 0 0 71,scrp 4 0 0 71,sndq fart 5,sndq gig2 10,chem 74 250,endm</span></span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
If you now hatch a Norn with the new genome, you can monitor it's gas and fardecrase levels while injecting him with the Gas chemical.</div>
<div class="separator" style="clear: both; text-align: left;">
When the Gas level reaches the threshold, the fart script is executed, fardecrase is injected, and promptly eliminates Gas from the Norn's body:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkzdmxlfNwSmDT8VwHseqT5V2bRJiO2k74IHHdl84bLxneJwU8Usi5SzvUlaPpSLxIO1x1p4eCyWaJ7OpwgbiiCobeCcyR-qAymYp5hLvOX8DDvi1pjZgmORMJPUl99KTpz8BvawaVcFzl/s1600/fart+elim.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkzdmxlfNwSmDT8VwHseqT5V2bRJiO2k74IHHdl84bLxneJwU8Usi5SzvUlaPpSLxIO1x1p4eCyWaJ7OpwgbiiCobeCcyR-qAymYp5hLvOX8DDvi1pjZgmORMJPUl99KTpz8BvawaVcFzl/s1600/fart+elim.PNG" height="302" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">After a Gas injection, the Norn Farts, getting a Fardecrase spike, which effectively destroys most of the Gas chemical in the Norn's bloodstream. Note that the elimination reaction is so fast, the fardecrase spike does'nt always have the time to fully show as in this example.</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
We now need to make gas production a digestive byproduct.</div>
<div class="separator" style="clear: both; text-align: left;">
Fortunately, in C1 the digestive model is relatively simple, as the only digested nutrient is starch.</div>
<div class="separator" style="clear: both; text-align: left;">
Once again, in the edited genome, go to the genes section, order by type, and find the "Reactions" section.</div>
<div class="separator" style="clear: both; text-align: left;">
Gene 142 is labelled as "Digestion" and mimics the process of converting ingested starch into usable body chemicals.</div>
<div class="separator" style="clear: both; text-align: left;">
Luckily for us, the initial reaction only produces glucose, leaving a free slot.</div>
<div class="separator" style="clear: both; text-align: left;">
Let's add gas generation as a byproduct of digestion :</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9dDl2CMxTmbdAXPb4zOOay8iR5kY7ZykWsIgA4jrZiW9zp9wi-U0LOQcjWSD5rgJ3Lf3Y8vvfyrlOq0vp_QuclzERjJKoIgYZ9xLGO1OJ1CGQ7dzt_ZCPT0_ry_JO8N8Qkxzfov5UXkFH/s1600/digestion.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9dDl2CMxTmbdAXPb4zOOay8iR5kY7ZykWsIgA4jrZiW9zp9wi-U0LOQcjWSD5rgJ3Lf3Y8vvfyrlOq0vp_QuclzERjJKoIgYZ9xLGO1OJ1CGQ7dzt_ZCPT0_ry_JO8N8Qkxzfov5UXkFH/s1600/digestion.PNG" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Now gas production inside your Norn truly is the product of the digestive process.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h2 class="separator" style="clear: both; text-align: left;">
Further tuning:</h2>
<div class="separator" style="clear: both; text-align: left;">
At this point we have a working farting Norn breed.</div>
<div class="separator" style="clear: both; text-align: left;">
Let's just tune it a bit to make it worthwhile.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
For now production of gas happens with each meal intake, meaning that our Norn is bound to fart regularly for a given food consumption.</div>
<div class="separator" style="clear: both; text-align: left;">
Let's make the behaviour slightly less systematic, and more realistic. </div>
<div class="separator" style="clear: both; text-align: left;">
We will add a natural decay for the Gas Chemical.That way a single meal won't be enough to trigger a fart, and the accumulated gas will naturally decay.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Select the 001 Gene ( the half lives gene ), and set the Gas Half life around 96:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQKReNVXZZH2FrX1x5YQzpc4EWMfqisc4b04AIFTl-zJZ1cwVYxg0DYgE3S5hkBRp6EGkk3W5uSEKnbm2S9R9yr3kkF8Kc8Pi3idLweuwMXf5OEVe63jh9cTZkdmexsi-27vQuEFF38khl/s1600/decay.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQKReNVXZZH2FrX1x5YQzpc4EWMfqisc4b04AIFTl-zJZ1cwVYxg0DYgE3S5hkBRp6EGkk3W5uSEKnbm2S9R9yr3kkF8Kc8Pi3idLweuwMXf5OEVe63jh9cTZkdmexsi-27vQuEFF38khl/s1600/decay.PNG" height="400" width="382" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Tuning this value is a delicate balance.</div>
<div class="separator" style="clear: both; text-align: left;">
Set it anywhere too fast ( low values ) for example less than 72, and even eating won't be able to raise the gas value as it will decay quicker than it is created.</div>
<div class="separator" style="clear: both; text-align: left;">
Set in anywhere too slow, and you won't even notice it decaying.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcyJNeMIqUlV7CiF-5CLO80YLc-rn-hl70dAlqSf9IHqeaqP-HRnevXfjKIVx2QvGGKT1CHSNi2umeFPxQrQkjLny0qo38sZ9P1KLHFKej-YAB8yLMAZ-SGTKnvhNliuGRI0xTC7v6con3/s1600/decaying2.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcyJNeMIqUlV7CiF-5CLO80YLc-rn-hl70dAlqSf9IHqeaqP-HRnevXfjKIVx2QvGGKT1CHSNi2umeFPxQrQkjLny0qo38sZ9P1KLHFKej-YAB8yLMAZ-SGTKnvhNliuGRI0xTC7v6con3/s1600/decaying2.PNG" height="298" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">An appropriate decay value eliminates Gas naturally, yet not keeping it from rising after a good meal.</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Now it will really take a fest to make a Norn fart, making the behaviour more anecdotal, realistic and less boring.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Let's also add a small animation to our fart.</div>
<div class="separator" style="clear: both; text-align: left;">
You could design this at will, so your ingame fart seem either fun, embarrassing or rude.</div>
<div class="separator" style="clear: both; text-align: left;">
As we've already done much, I'm personally opting for a sober animation, barely being a visual clue of which Norn just farted, so the whole thing is not overdone.</div>
<div class="separator" style="clear: both; text-align: left;">
Install the following script as the new fart script to mimic that :</div>
<div class="separator" style="clear: both; text-align: left;">
<span style="color: #ffe599;">scrx 4 0 0 71,scrp 4 0 0 71,anim [0404080812],sndq fart 5,sndq gig2 10,chem 74 250,endm</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
This is a basic chaining of the 04 08 and 12 positions ( you can match those numbers to the actual positions by looking for the pose genes in the genetics kit.</div>
<div class="separator" style="clear: both; text-align: left;">
Basically it will make the Creature lean forward a little.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1nTTR-E1iRIefDltB5CK27DepdEGU2RvX6RAw8e08TO0LV7PWJhLrRkqyw6ccfCPzU0EXpLRnz4sRHGTNCYSupzstCo4P7qYojc5g4r0E7QMXsJnPhq6hzeze50UirANcUNHbua912FuT/s1600/fartmov.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1nTTR-E1iRIefDltB5CK27DepdEGU2RvX6RAw8e08TO0LV7PWJhLrRkqyw6ccfCPzU0EXpLRnz4sRHGTNCYSupzstCo4P7qYojc5g4r0E7QMXsJnPhq6hzeze50UirANcUNHbua912FuT/s1600/fartmov.PNG" height="320" width="305" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
You can design and test your animations by directly running the corresponding commands ( just don't forget each pose is 2 digit long, even when the first one is 0 )</div>
<div class="separator" style="clear: both; text-align: left;">
<span style="color: #ffe599;"> anim [0404080812] </span></div>
<h2 class="separator" style="clear: both; text-align: left;">
</h2>
<h2 class="separator" style="clear: both; text-align: left;">
Other ideas:</h2>
<div class="separator" style="clear: both; text-align: left;">
At this point you could further tune the script to make it more interesting.</div>
<div class="separator" style="clear: both; text-align: left;">
Any further ideas are only showed here as an exercise for the reader, but will probably be integrated in an official Farting Norns breed release.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
- You could add better animations, by creating new pose genes.</div>
<div class="separator" style="clear: both; text-align: left;">
- You could include various reactions to farting, for example making it seem fun for boys, or embarrassing for girls.</div>
- You could make the laughing sound less systematic, by generating a random number at fart time, and only playing a laughing sound 1 in 4 times.This will make the laughing sound less likely to happen, and might keep people interested longer in your mod as it will provide some unsuspected behaviour even after some time of use.<br />
- You could randomize the sounds and animations between a couple variants.<br />
<br />
Just make sure you don't associate any punishment or reward with the Farting process.<br />
As it is an involuntary action upon which your Norn can't act, this would totally mess up it's learning process.<br />
<h2 class="separator" style="clear: both; text-align: left;">
Permanent integration in the game</h2>
<div class="separator" style="clear: both; text-align: left;">
At this point you have a fully working farting mechanism, and a genome from which to span new creatures with the ability to fart.</div>
<div class="separator" style="clear: both; text-align: left;">
We set all of the new genes as non mutable, so the behaviour isn't as likely to disappear a couple generations down.</div>
<div class="separator" style="clear: both; text-align: left;">
Keep in mind though that by breeding non farting with farting Norns, there's always a chance the kid won't inherit all the required genes from the Farting parent and that some kids might loose this ability.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
There's one last thing we need to do.</div>
<div class="separator" style="clear: both; text-align: left;">
We manually installed our script in the world, but if we ever choose to restore it from a new one, our behaviour will be lost, even for the Norns that have the correct genome ( the inner reaction will still occur, but no sound or animation will ever be produced )</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
To install our script in the game in a more permanent fashion, we will need to install it in the "Eden.sfc" world , that is used as a template for generating new worlds.</div>
<div class="separator" style="clear: both; text-align: left;">
To do so:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
1) save your current world ( by using any tool, or cheat that allows it, or by running the "<a href="http://sheeslostknowledge.blogspot.fr/2013/12/the-full-syssmnd-id-list-for-creatures.html">sys: cmnd 57604</a>" CAOS command )</div>
<div class="separator" style="clear: both; text-align: left;">
2) Backup your Eden.sfc file to a safe place should you need vanilla virgin worlds later on.</div>
<div class="separator" style="clear: both; text-align: left;">
3) Open the Eden.sfc world ( once again using any tool,cheat or by manually running "sys: cmnd 57601"</div>
<div class="separator" style="clear: both; text-align: left;">
3) Install your farting script with the appropriate "scrp 4 0 0 71" command</div>
<div class="separator" style="clear: both; text-align: left;">
4) Save the world again to Eden.sfc template ( cheat menus or "sys: cmnd 57604" )</div>
<div class="separator" style="clear: both; text-align: left;">
5) Return to your traditional world with "sys: cmnd 57601" again.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
From on now, whenever you restore or start a new world, the used Eden.sfc template will be your fart-enabled world.</div>
<h2 class="separator" style="clear: both; text-align: left;">
</h2>
<h2 class="separator" style="clear: both; text-align: left;">
</h2>
<h2 class="separator" style="clear: both; text-align: left;">
Distribution</h2>
<div class="separator" style="clear: both; text-align: left;">
You've made quite a few modifications to your game to enable the farting behaviour.</div>
<div class="separator" style="clear: both; text-align: left;">
Here's a summary of what files to include if you ever wanted to distribute such a breed:</div>
<ul>
<li>A couple of female and male creatures in the .exp format, freshly hatched from your new genome.You could include more than one couple to allow for more diversity and longer lasting changes when breeding with vanilla breeds.Alternatively you could provide only your .gen file and <a href="http://sheeslostknowledge.blogspot.fr/2014/01/generating-arbitray-in-game-eggs-from.html">a way for users to generate new Norns based on that genome.</a>This is a slightly more risky approach as if users choose to generate genomes from both farting and non farting Norns , some of the offspring might not be fully functional.</li>
<li>If designing a C2 breed, <a href="http://sheeslostknowledge.blogspot.fr/2014/01/generating-creatures-2-egg-files-with.html">distributing them as .egg files</a> will be a better option. </li>
<li>The fart.wav file to be put in the sound folder.</li>
<li>A way to install the farting script, either via a dedicated COB, or better yet by an automated installation via a custom tool.</li>
<li>Your new chemicals.str file containing your new chemicals definitions.Since other breeds might be conflicting with your changes, adding an installer that first <a href="http://sheeslostknowledge.blogspot.fr/2014/01/the-creatures-1-chemicalstxt-file-format.html">reads the original file</a> and then patches it is a more robust way to proceed.If you just overwrite any existing chemicals.str file, you risk destroying someone else's custom chemicals.</li>
<li>Your new Eden.sfc file for persistent installation of your mod.Leave this a choice to the end user though, as some might expect their "restore" option to restore a fully virgin standard C1 world.</li>
<li>An accurate documentation of what your modifications precisely do, just so users could solve any conflict with existing breeds or scripts.</li>
</ul>
That's a lot of work ! But it's necessary to make your work enjoyable by others.<br />
<br />
<br />
I hope you had fun and/or learnt things while designing this custom behaviour.<br />
Let me know if this helped you getting in the obscure and small community of Norn breed makers !<br />
More tutorials will follow later, covering the more conventional but way more involved process of designing purely aesthetic Norn breeds.<br />
<br />
Stay tuned ! The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com3tag:blogger.com,1999:blog-1790862754650770452.post-25213393726078633232014-01-17T23:55:00.000+01:002014-01-24T23:47:39.485+01:00Norns caesarean (saving the egg from a dead pregnant Norn)I read <a href="http://discoveralbia.blogspot.fr/2014/01/another-day-of-usual-oddities-in.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+DiscoverAlbia+%28Discover+Albia%29">a post</a> today on (the awesome) <a href="http://discoveralbia.blogspot.fr/">Discover Albia</a> blog and got slightly depressed by a random statement about the grief of loosing a pregnant Norn along with her egg.<br />
<br />
Not that it happened that much to me, maybe once at worst.Yet this was the wake up call I needed to be ready should this ever happen.<br />
So here's some CAOS black magic that will help you saving the egg from a pregnant Norn that passed away before getting to term.<br />
<br />
<a name='more'></a><br /><br />
<br />
By the time two Norns kisspop, a new child genome is generated with the "<span style="color: #ffe599;">new: gene</span>" command.<br />
This means as soon as it's conceived, there already exists a genome file in your genetics folder, fully describing what the child will be. <br />
<br />
The female is considered pregnant as soon as it's "Baby" variable is nonzero (it is set to the baby's moniker by the kisspop script)<br />
<br />
Setting a female pregnant is just a matter of running the "<span style="color: #ffe599;">setv baby tokn oxer</span>" command, where "oxer" is the wanted child genome (Here the purple mountain Norns one).<br />
<br />
Aborting an unwanted pregnancy is as simple as "<span style="color: #ffe599;">setv baby 0</span>" (I'm not judging, the need might arise)<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVwWP2F26N3Mvq-2hqaCZCz85SG2ZOJ7xYlUFQVvNkE09r0rCqfMmzznFR4_iD6jTQStOynrnbu14kbRyv4tyOiPUXLqcnheHVwOeiiKws-0IQxSAyL-RISzEPpynPD3DD5SNMX7F9g_8i/s1600/immaculee.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVwWP2F26N3Mvq-2hqaCZCz85SG2ZOJ7xYlUFQVvNkE09r0rCqfMmzznFR4_iD6jTQStOynrnbu14kbRyv4tyOiPUXLqcnheHVwOeiiKws-0IQxSAyL-RISzEPpynPD3DD5SNMX7F9g_8i/s1600/immaculee.PNG" height="271" width="320" /> </a></td><td style="text-align: center;"><br /></td><td style="text-align: center;"><br /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Albia, the only place where immaculate conception is likely to have ever occured.</td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
<br />
But I digress.<br />
<br />
Basically all of this is good news, as we've <a href="http://sheeslostknowledge.blogspot.fr/2014/01/generating-creatures-2-egg-files-with.html">already seen</a> that it is possible for us to <a href="http://sheeslostknowledge.blogspot.fr/2014/01/generating-arbitray-in-game-eggs-from.html">generate eggs from arbitrary genomes</a>.<br />
<br />
This means that even if you didn't act on time, you could easily recreate the lost baby In-vitro by <a href="http://sheeslostknowledge.blogspot.fr/2014/01/introduction-to-advanced-norn-genealogy_4.html">looking up it's genome in a family tree</a>.<br />
<br />
We will be trying another approach though. <br />
<br />
Forcing a stuck pregnancy is pretty easy.As seen in the egg generating article, it's just a matter of injecting the female Norn with a copious amount of progesterone (indicator of pregnancy progression), which will automatically trigger her "Lay an egg" involuntary action ( the corresponding script has the 4 0 0 65 classification ) once a given threshold is reached.<span style="font-family: "Courier New",Courier,monospace;"></span><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHetYBWnZAgAonF8erWhfxjj_hMNaB9vYvRu3vK7tTvv-z4-oH1MAPJc5nI3d3Vw_CYXfA2JOm-K6uGe0L14LaOVC1RSvWP-iW9ISr3udoRPkS0K3bMx6OO9n1Yg326dzfOKmy_0Icghp2/s1600/stuck+pregnancy.bmp" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHetYBWnZAgAonF8erWhfxjj_hMNaB9vYvRu3vK7tTvv-z4-oH1MAPJc5nI3d3Vw_CYXfA2JOm-K6uGe0L14LaOVC1RSvWP-iW9ISr3udoRPkS0K3bMx6OO9n1Yg326dzfOKmy_0Icghp2/s1600/stuck+pregnancy.bmp" height="320" width="314" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Reactivating a stuck pregnancy</td></tr>
</tbody></table>
<br />
Unfortunately for us, dead Norns don't react to involuntary actions triggers anymore (and that would be damn creepy anyway).Yet on a brighter note, death of the mother doesn't automatically kill the egg.<br />
<br />
We will need to mimic the egg laying process manually.<br />
We can do this by revamping the original egg laying script and removing mother related parts that are not needed anymore :<br />
<br />
<span style="color: #ffe599;">enum 4 1 2,doif dead gt 0,doif baby gt 0,sys: camt,dde: putv baby,setv var0 baby,setv var1 posl,addv var1 16,setv var2 limb,rndv var3 0 5,mulv var3 8,new: simp eggs 8 var3 2000 0,pose 0,setv clas 33882624,setv attr 64,setv obv0 var0,setv obv1 0,subv var2 hght,mvto var1 var2,slim,evnt targ,tick 900,dde: negg,endi,endi,next</span><br />
<br />
<br />
Long story short, this scripts looks through all your female Norns, and if one is both dead and pregnant, it lays it's egg as if it had naturally occurred, giving a chance to the otherwise lost offspring.<br />
If you want more information on what all of this means, just check out the birth process explanation on <a href="http://sheeslostknowledge.blogspot.fr/2014/01/generating-arbitray-in-game-eggs-from.html">the egg generation article</a>. <br />
<br />
You will have to act quick when death occurs, before the Norn disappears for good.<br />
Just use any of your <a href="http://double.co.nz/creatures/brainutilities.htm">favorite tools</a> to <a href="http://double.co.nz/creatures/programs/CCmdLine_exe.zip">inject the preceding CAOS</a> script, and a healthily egg should pop out by the unfortunate mother.<br />
<br />
Should you miss the opportunity , you will have to investigate your <a href="http://sheeslostknowledge.blogspot.fr/2014/01/introduction-to-advanced-norn-genealogy_4.html">Norns family tree</a>, to find out the baby's genome moniker and <a href="http://sheeslostknowledge.blogspot.fr/2014/01/generating-arbitray-in-game-eggs-from.html">revive it</a> through <a href="http://sheeslostknowledge.blogspot.fr/2014/01/generating-creatures-2-egg-files-with.html">other means.</a><br />
<br />
<br />
That's an useful if creepy tool to have under your belt.<br />
I really hope you'll never have to test it out. <br />
<br />
Great... I'm yet more depressed about dead Norns now ...<br />
At least some of them will now have a chance :)<br />
Take great care of them !The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-63541646745354666692014-01-15T10:42:00.001+01:002014-01-24T23:48:12.585+01:00Generating arbitray In-game eggs from CAOS commands, while also investigating the Norn reproductive system.<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio8ENMkQ8jrZriFDd193ToccO6ZvGtsnkCPL2KVzrVDegViB7JvPLbJB0L57LDgM4LBbZJ8fmD8rwlbUqTx55d0oNq-GnV5_fldfJcWRgHBnCkXjU0UJSntZBXbQwjIS7mGmATdmIgn17b/s1600/progegg.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio8ENMkQ8jrZriFDd193ToccO6ZvGtsnkCPL2KVzrVDegViB7JvPLbJB0L57LDgM4LBbZJ8fmD8rwlbUqTx55d0oNq-GnV5_fldfJcWRgHBnCkXjU0UJSntZBXbQwjIS7mGmATdmIgn17b/s1600/progegg.PNG" height="141" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
Okay, so in <a href="http://sheeslostknowledge.blogspot.fr/2014/01/generating-creatures-2-egg-files-with.html">a previous</a> article we've seen how to generate .egg files from genomes with a custom tool.<br />
Even if it may be a nice skill to add to your toolbox, it might not be the most practical everyday tool to inject genomes in your game.<br />
<br />
Wouldn't it be more practical if we could directly create ingame eggs from arbitrary genomes/couples as if they were just laid ? This is not only possible but also quite easy.<br />
<br />
Some available tools such as the <a href="http://double.co.nz/creatures/programs/genomeinjector.zip">Genome injector</a> on the awesome <a href="http://double.co.nz/creatures/">CDR website</a> already perform that feat. ( Be sure to check out the whole site, as it is definitely the single most complete and comprehensive resource on writing C1 and C2 custom programs )<br />
<br />
From there we could go the easy way, as Chris conveniently included a detailed description of the CAOS magic involved in spawning C2 eggs from genomes in the readme file the genome injector ( thanks for that Chris ! ).<br />
<br />
But I'll rather show you how you're supposed do find out that information by yourself when starting from scratch, as it will serve us better in the long run when investigating other undocumented game features.<br />
We will be doing this for C1, as Chris' tool only seems to work on Creatures 2.<br />
<br />
We will use the CAOS language,it's documentation and some external tools to try to understand what exactly happens during the whole Norn reproductive process, so we can mimic it with a custom and more practical tool. <br />
<br />
<a name='more'></a><br /><br />
<h2>
Things you'll need</h2>
A couple of tools and docs will be necessary for us to investigate the standard breeding process:<br />
<br />
- A way to execute CAOS commands ingame, to test and probe stuff.<br />
<ul>
<li>I most exclusively use <a href="http://double.co.nz/creatures/brainutilities.htm">Chris'</a> <a href="http://double.co.nz/creatures/programs/CCmdLine_exe.zip">CCmdline tool</a> for quick tests.It works with C1 and C2.</li>
<li>You could also use the CAOS injector tab of the corresponding game's genetic kit,</li>
<li>Or the CAOS console found in BobTweak for C2 ( along with some other useful tools, be sure to check that one out if you don't know about it ).</li>
</ul>
- Reliable CAOS documentation for <a href="http://www.gamewaredevelopment.com/downloads/cdn/creatures_caos_guide.pdf">C1</a> or <a href="http://www.gamewaredevelopment.com/downloads/COBcompiler/C2CAOS.doc">C2</a><br />
- An optional scriptorium browser for the appropriate game.<br />
It will make things easier, but you could also use hand crafted CAOS commands to retrieve the scripts you're interested in.<br />
<ul>
<li>Once again Chris is the man for <a href="http://double.co.nz/creatures/creatures2/scriptorium.htm">the C2 version</a></li>
<li>My <a href="http://sheeslostknowledge.blogspot.fr/p/the-creatures-kontrol-center-ckc.html">CKC available on this site</a> also features a scriptorium browser for C1 and C2.</li>
</ul>
- Some kind of Classification reference for the appropriate game, you'd better cross information from various sources as most are incomplete or contain mistakes.<br />
<ul>
<li>The C1 SDK PDF one (most accurate,and includes some third party ID's) </li>
<li><a href="http://creatures.wikia.com/wiki/Classification_system">The creatures wiki one (contains some errors)</a></li>
<li>The one <a href="http://www.gamewaredevelopment.com/downloads/COBcompiler/C2CAOS.doc">from the C2 Caos guide</a> ? </li>
<li>Once again my<a href="http://sheeslostknowledge.blogspot.fr/p/the-creatures-kontrol-center-ckc.html"> CKC tool </a>features a labelled scriptorium browser. </li>
</ul>
<ul>
</ul>
- Optionally a genetics kit, if you're really starting from scratch and don't know much about Creatures yet.<br />
<br />
<h2>
How babies happen:</h2>
You didn't think you'd be asking about that once again in your life , did you ?<br />
Well, it's all a matter of bees and flowers:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnrERVF7A8KD0HzIJ9lbHagvoD-YcqrQo_C7fM18hyphenhyphen1ED1oTKVZtGJoCWfhIEoF-TzWjRMR_2VYXimFGFoq-OMKPBwr-jDKlyGHj_UhEyD5NUqnG95Qi2f-nHkN_pnruFMnwnu3-I4IlMr/s1600/bees%2526flowers.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnrERVF7A8KD0HzIJ9lbHagvoD-YcqrQo_C7fM18hyphenhyphen1ED1oTKVZtGJoCWfhIEoF-TzWjRMR_2VYXimFGFoq-OMKPBwr-jDKlyGHj_UhEyD5NUqnG95Qi2f-nHkN_pnruFMnwnu3-I4IlMr/s1600/bees%2526flowers.PNG" /></a></div>
<br />
<br />
<br />
<br />
No seriously, in the Creatures games, babies or rather eggs, happen when Norns F**K. <br />
<br />
<br />
<br />
I'm not being rude here, it really is the exact name for the CAOS command used to trigger "sperm donation" as it is poetically described in the C1 CAOS reference document.<br />
<br />
We'll begin our investigation from the end of the reproductive chain as this is what is of most interest to us : generating eggs.<br />
<br />
<div style="text-align: left;">
In Creatures, eggs are laid by the mother Norn when the pregnancy reaches its term.<br />
<br />
The Genetics kit sheds some light on the process if you check out the description for the "Progesterone" chemical.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWECUMThIW8bWnk66jxFls6YiBe6b3wbSHBgz33_QPmI1qn8vCjLIuR_AOcZqixAgpD1diOqnV3CRaZ6-M4_aij0-21uCjCs9SnZDmBnClsFsUyVKH_fXjgm4lUDAr8GwH1Q37hsw1Ez6M/s1600/progesterone.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWECUMThIW8bWnk66jxFls6YiBe6b3wbSHBgz33_QPmI1qn8vCjLIuR_AOcZqixAgpD1diOqnV3CRaZ6-M4_aij0-21uCjCs9SnZDmBnClsFsUyVKH_fXjgm4lUDAr8GwH1Q37hsw1Ez6M/s1600/progesterone.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The description for this chemical reads "Produced progressively during pregnancy. When it reaches a threshold, it fires a receptor to cause the egg to be laid."</td></tr>
</tbody></table>
<br /></div>
<div style="text-align: left;">
In game mechanics terms, this chemical thresholds trigger a hardcoded "involuntary action".<br />
There's a few used involuntary actions in the game, such as sneezing, coughing, falling in a coma, laying an egg or ...dieing.<br />
<br />
There's also some free slots available for you to use if you want to implement new involountary actions to make your Norns more interesting.<br />
<br />
Once again, the Genetics kit is a good place to understand the process:<br />
Open your C1 gen kit, load the mum1.gen genome, then navigate to the genes tab.<br />
Order your genes by type, and navigate the "Receptor" section. ( not to be confused with the stimuli genes, some of which are also used during pregnancy )</div>
<div style="text-align: left;">
<span style="background-color: yellow;"><span style="background-color: white;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgU87iWwK1Yb21cvt1ZHxm4hkKkojIcKyeTSPNQsKOZEjZ6aobYxUl29I5YbysiJ_R3MIy0rDyGJa3xlSdJPdBTWbjD7JdO7NyIseVXkbaAqOSZan_GPMbJfuuzt8O5T6keQKV28A0IxtFX/s1600/Genetics+Kit+(no+windows+open).jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgU87iWwK1Yb21cvt1ZHxm4hkKkojIcKyeTSPNQsKOZEjZ6aobYxUl29I5YbysiJ_R3MIy0rDyGJa3xlSdJPdBTWbjD7JdO7NyIseVXkbaAqOSZan_GPMbJfuuzt8O5T6keQKV28A0IxtFX/s1600/Genetics+Kit+(no+windows+open).jpg" /></a></div>
<div style="text-align: left;">
<span style="background-color: yellow;"><span style="background-color: white;"><br /></span></span></div>
Gene 159 is labelled as "start laying" and operates by reacting to progesterone levels as expected.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLYuKLtudupW05lbSnsVnNaGX0WHCs04PVSkaWyZ81OwPMd8IOBePmnMZWTvFCCl2NC3LyiOePRdLfvuWK51W0T9z3EMgZoQVGOEiZF5pW0pg57A7ApK9SfzhyTuJn73Ga_h3W0bSclySU/s1600/(ID+%23+159)+022+Start+Laying+(F)+-+Receptor+(Biochemistry+Chemical+Receptor).jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLYuKLtudupW05lbSnsVnNaGX0WHCs04PVSkaWyZ81OwPMd8IOBePmnMZWTvFCCl2NC3LyiOePRdLfvuWK51W0T9z3EMgZoQVGOEiZF5pW0pg57A7ApK9SfzhyTuJn73Ga_h3W0bSclySU/s1600/(ID+%23+159)+022+Start+Laying+(F)+-+Receptor+(Biochemistry+Chemical+Receptor).jpg" height="320" width="284" /></a></div>
<br />
We can see how it triggers "Involuntary action 1" when progesterone levels get over the expected threshold. We now know that this action is the one associated with laying an egg ( we must note this as not all tools do map involuntary actions so explicitly ).<br />
<br />
"Involuntary actions" as most other aspects of the game are managed by associated CAOS scripts.<br />
By browsing the game scriptorium with one of our tools, we can find the associated script either by name ( if available ), or by trying to locate unique pieces of code that we expect to find.<br />
<br />
For example, without any documentation available, we could look for scripts that contain references to the egg sprites, to the "new: gene" command, or to the Egg classifier (2 5 2).<br />
<br />
The following script found as 4 0 0 65 will be our best candidate for the role.<br />
(
We can also note that the preceding and following scripts also seem to
concern involuntary actions, with their references to sounds of
sneezing, coughing and dieing.Which is a good indicator that we've found
what we wanted.)<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAnphHMQSt6Yu7ofORMijDKUn5e_EthcrbPzCdfACKeWvdDdCDxHvP0m8WDWBxD4dCUiaP7kTQGOlauaUAKqyluptgixIgyjunaGGbiws05oy4KFu-Bzi2qyd-RNUtN1LaTD1fuMb2JPcU/s1600/scriptarchive.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAnphHMQSt6Yu7ofORMijDKUn5e_EthcrbPzCdfACKeWvdDdCDxHvP0m8WDWBxD4dCUiaP7kTQGOlauaUAKqyluptgixIgyjunaGGbiws05oy4KFu-Bzi2qyd-RNUtN1LaTD1fuMb2JPcU/s1600/scriptarchive.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Here is a screenshot from the CKC's Script Archive applet, run in Scriptorium browsing mode, showing the EggLaying script known as 4 0 0 65.</td></tr>
</tbody></table>
<br />
Oddly enough, the egg laying script is classified as "Creatures->All Creatures -> Both sexes -> Lay an egg".<br />
Meaning it's not a female specific behaviour. There's probably a good reason for that ( simplification ? possibility for new sexless species ?) but it won't really matter for our needs.<br />
<br />
Let's rather take a look at the script and see what it does.<br />
You can fetch the script with your favorite CAOS console tool by feeding it: "<span style="font-family: "Courier New",Courier,monospace;">dde: scrp 4 0 0 65</span>"<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDHPJJdbT0UM0dFW1N4z4LuHfuh-wR5PRGOgXIFSQVKdh5KX2211NCrhnRQMfw1iYWVUM-yXQ_rkxfdH9yWiIdlHhau1p5v2yDuHPXcCzj9uhM_btpCKJ5t5smDl5DLUkDwbdJl6QtmU-y/s1600/ddegetscript.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDHPJJdbT0UM0dFW1N4z4LuHfuh-wR5PRGOgXIFSQVKdh5KX2211NCrhnRQMfw1iYWVUM-yXQ_rkxfdH9yWiIdlHhau1p5v2yDuHPXcCzj9uhM_btpCKJ5t5smDl5DLUkDwbdJl6QtmU-y/s1600/ddegetscript.PNG" /></a></div>
<br />
This is a slightly more readable version:<br />
<br />
<br />
<br />
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;">ltcy 1 255 255<br /><br />doif carr ne 0<br /> stop<br />endi<br /><br />doif baby gt 0<br /> pose 48<br /> wait 40<br /> setv var0 baby<br /> setv baby 0<br /> setv var1 posl<br /> addv var1 16<br /> setv var2 limb<br /> rndv var3 0 5<br /> mulv var3 8<br /> new: simp eggs 8 var3 2000 0 </span></span><br />
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;"> pose 0<br /> setv clas 33882624<br /> setv attr 64<br /> setv obv0 var0<br /> setv obv1 0<br /> subv var2 hght<br /> mvto var1 var2<br /> slim<br /> evnt targ<br /> tick 900<br /> dde: negg<br /> targ ownr<br /> stm# writ ownr 29<br /> wait 60<br />endi<br /><br />done<br /><br />endm</span></span><br />
<br />
<br />
So what does all of this mean ?<br />
With the help of the C1 CAOS guide, we can understand all of this:<br />
<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #ffe599;">ltcy 1 255 255 </span></span><br />
<br />
<span style="font-family: inherit;">Is used to mean that the involuntary action should not retrigger before "255" delay.</span><br />
<span style="font-family: inherit;">This is to give time </span>to the activating chemical do fade away and not lay more and more eggs at once<br />
<br />
<br />
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;">doif carr ne 0<br /> stop<br />endi</span></span><br />
<br />
<span style="font-family: inherit;">This stops the script if anybody is carrying the current object.</span><br />
<span style="font-family: inherit;">Probably to avoid bugs with creatures currently carried by the "edit" CAOS command, so they don't lay eggs while flying.</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<br />
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;">doif baby gt 0<br />....<br />endi</span></span><br />
<br />
This bloc will be executed only if "Baby" is set."Baby" contains the child moniker if current Norn is pregnant.<br />
This means all of this only happens if a Creature is pregnant.<br />
Even with a massive injection of Progesterone, an unfertilized Norn won't lay any egg.<br />
This makes sense to me.<br />
(This might also be an interesting spot to implement a new game mechanism such as the possibility for Norns to lay unfertilised eggs that could be later eaten? Come on, don't frown on me, you're doing the same for hens already.Yumm, scrambled Norn ovary byproduct with beacon !)<br />
<br />
The contents of the DOIF bloc are the core of the egg laying process:<br />
<br />
<span style="color: #b6d7a8;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #ffe599;">pose 48</span> # Makes the creature Crouch for laying the egg<br /> <span style="color: #ffe599;">wait 40 </span> # Small delay<br /> <span style="color: #ffe599;">setv var0 baby </span> # put the Baby's moniker in global variable Var0<br /> <span style="color: #ffe599;">setv baby 0 </span> # Clear the "Baby" flag from the norn, she's not pregnant anymore<br /> <span style="color: #ffe599;">setv var1 posl </span> # Put the current creatures Left position in global variable var1<br /> <span style="color: #ffe599;">addv var1 16 </span> # Add 16 to the variable ( 16 is half a Norn, this centers the egg on the mother<br /> <span style="color: #ffe599;">setv var2 limb </span> # Put the lower creature's limit in global variable var2, this "finds the ground"<br /> <span style="color: #ffe599;">rndv var3 0 5 </span> # Roll a 6 sided dice, and put result in var3<br /> <span style="color: #ffe599;"> mulv var3 8 </span> # Multiply that value by 8 ( used to index imagefiles from 1-6 egg number later<br /> <span style="color: #ffe599;">new: simp eggs 8 var3 2000 0</span> # Create a new egg,from "eggs" sprite, with 8 states,pick the appearance N°"var3"<br /> # From now on, following the "new:" command, targ is no longer the mother but the egg.<br /> <span style="color: #ffe599;"> pose 0 </span> # Sets the egg sprite to the first one ( smallest )<br /> <span style="color: #ffe599;">setv clas 33882624</span> # Sets the egg class for this egg<br /> <span style="color: #ffe599;">setv attr 64</span> # Sets the egg attributes ( roombound )<br /> <span style="color: #ffe599;"> setv obv0 var0 </span> # Puts the Baby moniker saved in global var0 inside the egg's onw obv0 variable<br /> <span style="color: #ffe599;">setv obv1 0 </span> # Puts 0 in obv1 local variable, ass we will see later, this will be the babies sex (0=random)<br /> <span style="color: #ffe599;">subv var2 hght </span> # Subtracts egg height from found ground level ( Y axis is Top->Down )<br /> <span style="color: #ffe599;">mvto var1 var2</span> # Places the egg correctly at mother's center, and groundlevel-eggsize<br /> <span style="color: #ffe599;"> slim </span> # Enables the egg "limits"<br /> <span style="color: #ffe599;">evnt targ </span> # Triggers the "New egg" indicator in the status bar.<br /> <span style="color: #ffe599;">tick 900 </span> # Sets the egg's timer to 900<br /> <span style="color: #ffe599;">dde: negg </span> # Updates number of natural eggs in the world<br /> <span style="color: #ffe599;">targ ownr </span> # Targets back the mother<br /> <span style="color: #ffe599;">stm# writ ownr 29</span> # Fires the 29 hardcoded stimulus in the mother<br /> <span style="color: #ffe599;"> wait 60 </span> # small pause</span></span><br />
<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">Then we're only left with the cleanup: </span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #ffe599;">done </span> <span style="color: #b6d7a8;"># signal that we're done so the creature can resume normal life</span><br /><span style="color: #ffe599;">endm </span> <span style="color: #b6d7a8;"># Mandatory endmacro command</span></span> <br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: inherit;">So what does all of this teach us ?</span><br />
<span style="font-family: inherit;">If we take out of the whole housekeeping stuff, and gameplay specifics from the script,</span><br />
<span style="font-family: inherit;">spawning a new egg boils down to running:</span><br />
<br />
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;"> new: simp eggs 8 <EggImageNumber*8> 2000 0<br /> pose 0 <span style="color: #b6d7a8;"># This sets initial egg size,might start bigger</span><br /> setv clas 33882624 <br /> setv attr 64 <br /> setv obv0 <MONIKER> <br /> setv obv1 <SEX> <br /> mvto <Xpos> <Ypos> <span style="color: #b6d7a8;"># Put the egg somewhere</span><br /> slim <span style="color: #b6d7a8;"> # Enables the egg "limits"</span><br /> tick 900 <span style="color: #b6d7a8;"># Sets the egg's timer to 900</span></span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #ffe599;"> dde: negg <span style="color: #b6d7a8;"># Use if you want that egg to count as one egg in game stats.</span></span></span><br />
<span style="font-family: inherit;"> </span><br />
<br />
<span style="font-family: inherit;">We got rid of all uncontrolled stuff to replace it with our known wanted values.We also don't consider the new egg as a natural egg, so we don't update anything in the game interface.</span><br />
<br />
<span style="font-family: inherit;">We could also remove the "mvto" command, and add an "edit" one at the end of the script, so the newly injected egg ends up in the hand ( this won't disturb the egg if you don't spawn it starting at full size ) </span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Additionally, we are still using a predefined and already existing (this is mandatory !) child genome moniker.</span><br />
<span style="font-family: inherit;">To generate one at runtime we might rather use the "new: gene" command such as in :</span><br />
<span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;"> <span style="color: #ffe599;">new: gene tokn <MotherMoniker> tokn <FatherMoniker> obv0</span></span></span><br />
or<br />
<br />
<span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span><span style="color: #ffe599;"><span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;">new: gene tokn <MotherMoniker> 0 obv0 </span></span></span></span></span><br />
for mono parental child generation.<br />
<br />
<span style="font-family: inherit;">Before you get straight to making new eggs though, let's just see what happens to the newly laid egg.</span><br />
<span style="font-family: inherit;">The "</span><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #ffe599;">tick 900</span>" </span>command in the original scripts, sets the egg timer value to "900" once laid.<br />
<br />
You could further check the 2 5 2 9 ( Simple -> Eggs ->Norn Egg -> Timer ) script to see what happens once the egg gets into the world, but this is a much longer script.<br />
I won't cover it in this article, but what happens next is that at regular intervals the egg grows in size.<br />
Once the max size is reached, the next timer tick plays the "about to hatch" animation and sounds, and creates the new creature.<br />
The last timer tick then destroys the remaining egg shell after some time. <br />
<br />
<br />
<h2>
Finally : generating your own ingame eggs</h2>
That's it ! we now know how to generate our own eggs.<br />
Here are some CAOS snippets for the various creation scenarios you might want to use.<br />
<br />
Remember we have control of all those parameters to get the expected behaviour:<br />
<ul>
<li>We can pick mom and dad monikers at will ( or spawn eggs from one single moniker )</li>
<li>We can either create an egg for an existing moniker, or generate one from any random creatures couple ( even dead ones).We only need to have their .gen files ( The names of all .gen files map to the creature's monikers.)</li>
<li>We can spawn eggs at any state: small or grown.</li>
<li>We can choose the eggs sex or set it as random</li>
<li>We can control the Egg's appearance.</li>
<li>We can't control the eggs timer so it grows slower or faster, as this is reset in the timer script at each cycle. </li>
<li>We can spawn Eggs anywhere we want them, or make them user placable.</li>
</ul>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTR_o1xtDIDWyewc8oNg7hKM8NkDA0TlEkQWabPQli6wGm1agGNFZsiQFHHFhj1ebckBzXcqxQKYOJTmh7v-tyf1YU-YrAV5ngM5O-hYk2-g5rtfNoSXJnL3Q3FrBEJU089zYCmunlkp7i/s1600/progegg.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTR_o1xtDIDWyewc8oNg7hKM8NkDA0TlEkQWabPQli6wGm1agGNFZsiQFHHFhj1ebckBzXcqxQKYOJTmh7v-tyf1YU-YrAV5ngM5O-hYk2-g5rtfNoSXJnL3Q3FrBEJU089zYCmunlkp7i/s1600/progegg.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Yay! an egg out of nowhere from a CAOS command !</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDHPJJdbT0UM0dFW1N4z4LuHfuh-wR5PRGOgXIFSQVKdh5KX2211NCrhnRQMfw1iYWVUM-yXQ_rkxfdH9yWiIdlHhau1p5v2yDuHPXcCzj9uhM_btpCKJ5t5smDl5DLUkDwbdJl6QtmU-y/s1600/ddegetscript.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDHPJJdbT0UM0dFW1N4z4LuHfuh-wR5PRGOgXIFSQVKdh5KX2211NCrhnRQMfw1iYWVUM-yXQ_rkxfdH9yWiIdlHhau1p5v2yDuHPXcCzj9uhM_btpCKJ5t5smDl5DLUkDwbdJl6QtmU-y/s1600/ddegetscript.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<h3>
To make a random sex egg from a single genome ( here Purple mountain Norn ): </h3>
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;">new: simp eggs 8 8 2000 0,pose 0,setv clas 33882624,setv attr 64,setv obv0 tokn 0XER,setv obv1 0,mvto 2682 870,slim,tick 900</span></span><br />
<br />
<h3>
To make a carryable egg from a single genome ( you can't put it in the incubator before it reaches it's max size yet ):</h3>
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;">new: simp eggs 8 8 2000 0,pose 0,setv clas 33882624,setv attr 64,setv obv0 tokn 0XER,setv obv1 0,slim,tick 900,edit</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<br />
<h3>
<span style="font-family: inherit;">To spawn a fully grown egg that will hatch as soon as dropped:</span></h3>
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;">new: simp eggs 8 8 2000 0,pose 3,setv clas 33882624,setv attr 2,setv obv0 tokn 0XER,setv obv1 0,slim,tick 20,edit</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<br />
<h3>
<span style="font-family: inherit;">To spawn a fully grown egg that will hatch quickly, from 2 parent genomes :</span></h3>
<span style="color: #ffe599;"><span style="font-family: "Courier New",Courier,monospace;">new: simp eggs 8 8 2000 0,pose 3,setv clas 33882624,setv attr 64,new: gene tokn 1WGR tokn 2YZL obv0,setv obv1 0,mvto 2682 870,slim,tick 20</span></span><br />
<span style="font-family: inherit;"></span><br />
<h3>
<span style="font-family: inherit;"><br /></span></h3>
<h2>
<span style="font-family: inherit;">Closing words</span></h2>
<span style="font-family: inherit;">I hope this was interesting.Generating ingame egg files from arbitrary genomes can be an useful and practical addition to your Creatures mad scientist skillset.</span><br />
<span style="font-family: inherit;">Also contrary to the egg file generation mechanism shown in a previous article, this not only is more practical for everyday use but also works with C1.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">All of these articles aren't purely coincidental. Once we've got all the bases covered, a future article will deal with massively and automatically mixing arbitrary genomes, and producing the corresponding eggs.</span><br />
<br />
<span style="font-family: inherit;">Basically, I will show you how to write a script that takes a set of Norn genomes, simulate them breeding for an arbitrarly high number of generations, and then import ingame some of the resulting children.</span><br />
<span style="font-family: inherit;">I use this possibility to check stability of my new genome/breeds over multiple generations, or to check long term compatibility when mixing various breed genomes.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">If you want to know more about that, stay tuned !</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Happy binary breeding!</span><br />
<span style="font-family: inherit;"><br /></span>
<br />
<h2>
<span style="font-family: inherit;"><br /></span></h2>
<h2>
<span style="font-family: inherit;"> </span></h2>
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<br />
<ul>
</ul>
The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com2tag:blogger.com,1999:blog-1790862754650770452.post-80320803363173995592014-01-12T23:59:00.002+01:002014-01-24T23:49:05.478+01:00Parsing C2 GameLog files with python.In this post we will see how to precisely parse a C2 Gamelog file.<br />
This file is an ordered collection of all main events happening in Albia : Birth, Ageing, Dieing, getting a Name, Exports or Imports. <br />
Parsing it can be useful to redraw a full timeline of stuff happening in your world, or to see which Norns are still alive or were ever used, if you need to perform some cleanup in the game folder ( by default, genomes and sprites files accumulate in the game folder for each Norn and are never removed )<br />
<br />
Whatever your needs are, I hope yo will find this quick reference useful. <br />
<br />
<a name='more'></a><br /><br />
<h2>
The file format:</h2>
Once again, this is a format for which <a href="http://www.gamewaredevelopment.com/cdn/CDN_more.php?CDN_article_id=95#gamelog">documentation exists</a>.<br />
<br />
Oddly enough, the file in my game seems to be messed up regarding this format ( and also by any logical standards.)<br />
<br />
The standard defines the file as a series of entries, one by line; having the following format :<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;"><MONIKER> | <TIMESTAMP> | <ACTION> | <PARAMS> |</span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">Despite this , the GameLog file in my own game seems to rather be of the form:</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;"><MONIKER> | <TIMESTAMP> | <ACTION><PARAMS> | </span><br />
<br />
<br />
<br />
It doesn't seem that the game cares that much about this mess though.<br />
Chances are the file is as it name implies merely a log, and the information is never pulled out of it again.<br />
<br />
Here are the fields meanings:<br />
<br />
<Moniker>: the 4 char identifier, unique for each creature that ever lived.<br />
<br />
<TIMESTAMP>: The date at which the event occurred. This is in the UNIX timestamp format.We can easily convert it to readable formats inside our programs, but keeping it in this numerical format allows for quick and painless ordering of events.<br />
<br />
<Action>: is the registered event, it is composed of only one letter , with the following meaning :<br />
<br />
B : Birth<br />
A : Creature has aged.<br />
D : Creature has died<br />
N : Creature was given a name( we used that <a href="http://sheeslostknowledge.blogspot.fr/2014/01/introduction-to-advanced-norn-genealogy_4.html">there </a>)<br />
E : Creature was exported<br />
I : Creature was imported<br />
<br />
<PARAMS> is optional and is an additional information regarding the event.<br />
Only A and N events have additional params.<br />
<br />
For A : the additional param is a number, describing the lifestage a creature has reached.<br />
<br />
0:Baby<br />
1:Child<br />
2:Adolescent<br />
3:Youth<br />
4:Adult<br />
5:Old<br />
6 :Senile <br />
<br />
<br />
For N: the additional parameter is the Name the creature was given.<br />
<br />
<br />
<span style="font-family: inherit;">That's it, there's not much to it , we can get to </span><br />
<h2>
<span style="font-family: inherit;">Parsing a Gamelog file with python:</span></h2>
<span style="font-family: inherit;">This will read the GameLog, pack it in a convenient structure, and then print out the timeline for any Norn you want.</span><br />
<span style="font-family: inherit;">Obviously, depending on the information you're interested in, other structures might provide quicker lookup methods( if you wanted to lookup events by Norn name for example.But keep in mind the moniker is the de-facto creature "unique identifier" to use wherever possible.Converting it to a name should only be a post processing commodity). </span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><br /></span></span>
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><br /></span></span>
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">from datetime import datetime<br /><br />GameLogPath="c:/Creatures2/History/Gamelog"<br />GameLog=open(GameLogPath,).readlines()<br /><br />Lifestages=["Baby","Child","Adolescent","Youth","Adult","Old","Senile","Kaputt"]<br /><br /><br />Evts=[]<br />for line in GameLog:<br /> line=line.rstrip('\n')<br /> Fields=line.split("|")<br /><br /> # Parsing the structure<br /> if Fields[2][0] == "N":<br /> Evts.append({"Moniker":Fields[0],"Timestamp":Fields[1],"Action":Fields[2][0],"Name":Fields[2][1:]})<br /> elif Fields[2][0] == "A":<br /> Evts.append({"Moniker":Fields[0],"Timestamp":Fields[1],"Action":Fields[2][0],"Stage":Fields[2][1:]})<br /> else:<br /> Evts.append({"Moniker":Fields[0],"Timestamp":Fields[1],"Action":Fields[2]})<br /><br /><br />who = raw_input("Enter a moniker: ")<br /><br />for event in Evts:<br /> if event["Moniker"]==who:<br /> date=datetime.fromtimestamp(int(event["Timestamp"])).strftime("%a, %d %b %Y %X %Z GMT")<br /> print who,<br /> if event["Action"]=="B":<br /> print "is born on", date <br /> if event["Action"]=="A":<br /> print "aged to",Lifestages[int(event["Stage"])], "on" ,date<br /> if event["Action"]=="D":<br /> print "died on", date<br /> if event["Action"]=="N":<br /> print " Was named",event["Name"],"on", date<br /> if event["Action"]=="E":<br /> print " Was exported on", date<br /> if event["Action"]=="I":<br /> print " Was imported on", date</span></span></span><br />
<br />
<br />
Running this code produces this kind of output :<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;">Enter a moniker: 7TML<br />7TML is born on Sat, 14 Dec 2013 14:57:36 GMT<br />7TML aged to Child on Sat, 14 Dec 2013 15:05:26 GMT<br />7TML aged to Adolescent on Sat, 14 Dec 2013 17:45:56 GMT<br />7TML aged to Youth on Sat, 14 Dec 2013 17:52:39 GMT<br />7TML aged to Adult on Sun, 15 Dec 2013 18:58:46 GMT<br />7TML aged to Old on Sun, 22 Dec 2013 19:43:00 GMT<br />7TML aged to Senile on Sun, 29 Dec 2013 15:26:24 GMT<br />7TML aged to Kaputt on Sun, 29 Dec 2013 18:03:49 GMT<br />7TML died on Sun, 29 Dec 2013 18:03:49 GMT</span></span></span><br />
<br />
<br />
Poor "7TML", he lived such a long Norn life without even getting a name.<br />
Well, at least he died peacefully. <br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><br /></span></span>The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com0tag:blogger.com,1999:blog-1790862754650770452.post-6663786834357112252014-01-11T18:31:00.000+01:002014-01-25T15:38:14.685+01:00The Creatures 1 chemicals.txt file format.For some odd reason, one of the most commonly usable file in the Creatures series, the Chemicals.txt file, format is still totally undocumented in 2014.<br />
<br />
Maybe somebody did document it and his work was lost in time ? Maybe I'm stupid and this is considered such common knowledge that nobody ever thought writing about it would be worth it ?<br />
Anyway, I take the opportunity to publish the information here so nobody has to find it out by himself again if ever needed.<br />
<br />
The Chemicals.txt file contains the list of all chemicals in game, their associated name, as well as their description (as used in the genetics kit)<br />
It's a valuable resource when writing your own programs for dynamically establishing the various chemicals names without worrying about the various countries variations, or custom chemicals installed by various players.<br />
<i><br /></i>
<i><b>26/01/2014 Update: </b>Seems I've committed a small mistake (sorry, but I'm mostly writing all of that as I do it, so some things might need tuning afterwards)</i><br />
<i>Although The Chemicals.txt holds chemical description data, it's the chemicals.str file that holds the current actively used ingame chemicals list.</i><br />
<i>The chemicals.str file has exactly the same file format, except it doesn't include the chemicals descriptions and that each entry length prefix is only one byte long instead of 2.</i><br />
<i>This doesn't prevent you from using the Chemicals.txt file as a chemical description source, but the most up to date data synchronised with your game status is to be extracted from the chemicals.str file.</i><br />
<a name='more'></a><br />
<br />
Fortunately for us the file is of quite simple structure and can be easily reversed and parsed.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNlqRgixN-tL400pZJiU5pA7T6bBhvg56_MVKvJiD-SgxaLoW7tl-42wUOEbHwEoykzOC-UKquxEvFnlRLHuCmAYuDgVYFCunQVXrnPpdguDXAE_RCjIuOInMCdqMm7n2rWRBNRwxvMAy9/s1600/chemicals.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNlqRgixN-tL400pZJiU5pA7T6bBhvg56_MVKvJiD-SgxaLoW7tl-42wUOEbHwEoykzOC-UKquxEvFnlRLHuCmAYuDgVYFCunQVXrnPpdguDXAE_RCjIuOInMCdqMm7n2rWRBNRwxvMAy9/s1600/chemicals.PNG" height="198" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The C1 Chemicals.txt file in all it's glory</td></tr>
</tbody></table>
<br />
By just opening it in a Hex editor, it's structure is pretty obvious:<br />
<br />
It contains no header whatsoever, but a series of entries of chemical names.<br />
Each entry is of the format<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><Entrylength ( 2 bytes ) ><Chemical Name (Entrylength long)> </span><br />
<br />
There's no numbering scheme or indexation in the file whatsoever, entries are just read sequentially, and crammed into an array ( starting at 0, ending at 255 ) so you can later reference them by number in your program.Their number is defined as the position they appear at in the file.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoma2yhYLen61na3jkCQUQOG-F2x_cvs_rWSJJL4tYwrpKuq4otDU5qcSug4ZSLkGvNtgfoe1zjzj597_DPhc4GWyk7FplefUnG1egRMYlA2hSOTl7NIcx0a1y2aMd-HLD8Yqqujt1SATn/s1600/hunger.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoma2yhYLen61na3jkCQUQOG-F2x_cvs_rWSJJL4tYwrpKuq4otDU5qcSug4ZSLkGvNtgfoe1zjzj597_DPhc4GWyk7FplefUnG1egRMYlA2hSOTl7NIcx0a1y2aMd-HLD8Yqqujt1SATn/s1600/hunger.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The "Hunger" entry: a<span style="color: blue;"> length of 6, coded on 2 bytes</span>, followed by <span style="color: red;">6 bytes string containing the chemical name </span></td></tr>
</tbody></table>
<br />
<br />
Once the 256th entry is reached, there is an empty 4 byte string "\x00\x00\x00\xx00", serving as a delimiter to signal further entries are chemical descriptions.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK9zEwr5M5m3mL73lpftHl_276mbJJpWzdaPDR_rGHQqAwfDFdtTKGOHskThyphenhyphenCnp4IwNHnW7sMheoKAtK5WusOCutBMFRdZYpwQbqvnreqbsHh6pZ4aYmc2QnMcHXS1Sozbk7urmcKVgzI/s1600/separatior.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK9zEwr5M5m3mL73lpftHl_276mbJJpWzdaPDR_rGHQqAwfDFdtTKGOHskThyphenhyphenCnp4IwNHnW7sMheoKAtK5WusOCutBMFRdZYpwQbqvnreqbsHh6pZ4aYmc2QnMcHXS1Sozbk7urmcKVgzI/s1600/separatior.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="color: red;">Antigen 7 </span>is the last chemical entry, followed by the <span style="color: blue;">"\x00\x00\x00\x00"</span> marker, from now on all further entries are <span style="color: lime;">chemical descriptions</span></td></tr>
</tbody></table>
<br />
Chemical descriptions share the same format as the chemical names entries.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><Entrylength (2 bytes)><Chemical Description (Entrylength long)> </span><br />
<br />
They are also read sequentially, the first chemical description mapping to the first chemical, etc... <br />
<br />
<br />
<br />
<br />
The final file format therefore is divided in three main blocs, <span style="color: red;">chemical names</span>, <span style="color: blue;">transition marker</span>, <span style="color: #6aa84f;">chemical descritptions</span> :<br />
<br />
<br />
<span style="color: red;"><span style="font-family: "Courier New",Courier,monospace;"><1stEntrylength (2 bytes)><1stChemical Name (1stEntrylength long)></span></span><br />
<span style="color: red;"><span style="font-family: "Courier New",Courier,monospace;"><2ndEntrylength (2 bytes)><2ndChemical Name (2ndEntrylength long)> </span></span><br />
<span style="color: red;"><span style="font-family: "Courier New",Courier,monospace;">...</span></span><br />
<span style="color: red;"><span style="font-family: "Courier New",Courier,monospace;"><NthEntrylength (2 bytes)><NthChemical Name (NthEntrylength long)></span></span><br />
<span style="color: red;"><span style="font-family: "Courier New",Courier,monospace;">... </span></span><br />
<span style="color: red;"><span style="font-family: "Courier New",Courier,monospace;"><256thEntrylength (2 bytes)><256thChemical Name (256thEntrylength long)</span></span><br />
<br />
<span style="color: blue;"><span style="font-family: "Courier New",Courier,monospace;"><\x00\x00\x00\x00 (4 bytes) marker signialing further entries are chemical descriptions > </span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="color: #93c47d;"><span style="font-family: "Courier New",Courier,monospace;"><1stEntrylength (2 bytes)><1stChemical Description(1stEntrylength long)></span></span><br />
<span style="color: #93c47d;"><span style="font-family: "Courier New",Courier,monospace;"><2ndEntrylength (2 bytes)><2ndChemical Description(2ndEntrylength long)> </span></span><br />
<span style="color: #93c47d;"><span style="font-family: "Courier New",Courier,monospace;">...</span></span><br />
<span style="color: #93c47d;"><span style="font-family: "Courier New",Courier,monospace;"><NthEntrylength (2 bytes)><NthChemical Description(NthEntrylength long)</span></span><br />
<span style="color: #93c47d;"><span style="font-family: "Courier New",Courier,monospace;">... </span></span><br />
<span style="color: #93c47d;"><span style="font-family: "Courier New",Courier,monospace;"><256thEntrylength (2 bytes)><256thChemical </span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">Description </span>(256thEntrylength long)</span></span><br />
<br />
<br />
Now we know that, we can simply parse the file within our programs to get an updated list of all ingame chemicals.<br />
<br />
The following python script illustrates loading the Chemicals.txt file into a list, so each Chemical can be accessed by number; and his name and description be easily recovered:<br />
( The example python file can be found here : <a href="https://github.com/LoneShee/SLKExamples/blob/master/ParseC1chemicalsfile_example.py">ParseC1chemicalsfile_example.py</a> ) <br />
<br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">import struct<br /><br />number=0<br />Chemicals={}<br /><br />f = open("Chemicals.txt", "rb")<br />try:<br /> byte = struct.unpack("H",f.read(2))[0]<br /> while byte != "\x00\x00":</span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> # We are reading a chemical entry</span></span></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span> if number < 256:<br /> Chemname = f.read(byte)<br /> Chemicals[number] = {"number":number,"name":Chemname}<br /> #print Chemicals[number]["number"],":",Chemicals[number]["name"]<br /> number+=1<br /> byte = struct.unpack("H",f.read(2))[0]</span></span><br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> # We are skipping the \x00</span></span></span></span></span></span><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">\x00</span></span></span></span></span></span><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">\x00</span></span></span></span></span></span><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">\x00 marker</span></span></span></span></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span></span></span> elif number == 256:<br /> byte = struct.unpack("H",f.read(2))[0]<br /> number+=1</span></span><br />
<br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> # We are reading a chem description entry</span></span></span></span></span></span></span></span><br />
<span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span></span></span></span></span> elif number < 513:<br /> Chemdesc=f.read(byte)<br /> Chemicals[number-257]["desc"]=Chemdesc<br /> number+=1<br /> byte = struct.unpack("H",f.read(2))[0]<br /> else:<br /> break<br />finally:<br /> f.close()<br /><br /># printout chemicals recovered :<br />for chemical in Chemicals:<br /> print Chemicals[chemical]["number"],":",Chemicals[chemical]["name"],"(",Chemicals[chemical]["desc"],")"</span></span><br />
<br />
Sure enough we get the expected result:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">0 : <NONE> ( )<br />1 : Pain ( Drive levels... )<br />2 : Need for Pleasure ( )<br />3 : Hunger ( )<br />4 : Coldness ( )<br />5 : Hotness ( )<br />6 : Tiredness ( )<br />7 : Sleepiness ( )<br />8 : Loneliness ( )<br />9 : Crowded ( )<br />10 : Fear ( )<br />11 : Boredom ( )<br />12 : Anger ( )<br />13 : Sex Drive ( )<br />14 : not_allocated2 ( Un-used drive levels )<br />15 : not_allocated3 ( )<br />16 : not_allocated4 ( )</span>...<br />
<br />
Hope some of you will find that useful !<br />
<br />The Lone Sheehttp://www.blogger.com/profile/03580641374827312224noreply@blogger.com3