| SITE ANNOUNCEMENTS: | |
|---|---|
| |
User:Quietust/parsebody.php
From Dwarf Fortress Wiki
<?
$verbose = 0;
$filter = 'all';
array_shift($argv);
while (count($argv) > 0)
{
$arg = array_shift($argv);
if ($arg == '-verbose')
$verbose = 1;
else $filter = $arg;
}
function verbose ($text)
{
global $verbose;
if ($verbose)
echo "$text\n";
}
function notice ($text)
{
echo "$text\n";
}
function warning ($text)
{
echo "WARNING - $text\n";
}
function error ($text)
{
echo "ERROR - $text\n";
exit;
}
function readToken ($file)
{
$token = '';
while (1)
{
$c = fgetc($file);
if (feof($file))
return 0;
if ($c == '[')
break;
}
while (1)
{
$c = fgetc($file);
if (feof($file))
return 0;
if ($c == '[')
warning("Unterminated token '$token' found!");
if ($c == ']')
break;
$token .= $c;
}
return explode(':', $token);
}
function readBodies (&$bodies, $in)
{
$partname = $partdata = 0;
$bodyname = $bodydata = 0;
while (1)
{
$token = readToken($in);
if (!$token)
{
if ($partname)
{
$bodydata[$partname] = $partdata;
$partname = $partdata = 0;
}
if ($bodyname)
{
$bodies[$bodyname] = $bodydata;
$bodyname = $bodydata = 0;
}
break;
}
switch ($token[0])
{
case 'BODY':
if ($partname)
{
$bodydata[$partname] = $partdata;
$partname = $partdata = 0;
}
if ($bodyname)
{
$bodies[$bodyname] = $bodydata;
$bodyname = $bodydata = 0;
}
$bodyname = $token[1];
$bodydata = array();
break;
case 'BP':
if ($partname)
{
$bodydata[$partname] = $partdata;
$partname = $partdata = 0;
}
$partname = $token[1];
$partdata = array('id' => $partname, 'name' => $token[2]);
break;
case 'UPPERBODY':
case 'LOWERBODY':
case 'HEAD':
case 'GRASP':
case 'STANCE':
$partdata[$token[0]] = 1;
break;
case 'CON':
case 'CON_CAT':
case 'CATEGORY':
case 'CONTYPE':
$partdata[$token[0]] = $token[1];
break;
// ignore other tokens
}
}
}
function tracePart ($body, $part)
{
if (isset($part['UPPERBODY']))
{
verbose("The $part[name] bone IS the upper body - all done");
return TRUE;
}
$types = 0;
$numcon = $numcat = $numtype = 0;
if (isset($part['CON']))
{
$types++;
if (!isset($body[$part['CON']]))
{
warning("Body part $part[id] connects to nonexistent part $part[CON]!");
return FALSE;
}
$bp = $body[$part['CON']];
verbose("The $part[name] bone's connected to the $bp[name] bone");
if (tracePart($body, $bp))
$numcon++;
}
if (isset($part['CON_CAT']))
{
$types++;
$found = FALSE;
foreach ($body as $bp)
{
if (isset($bp['CATEGORY']))
{
if ($part['CON_CAT'] == $bp['CATEGORY'])
{
$found = TRUE;
if ($numcat)
verbose("...and the $part[name] bone's connected to the $bp[name] bone");
else verbose("The $part[name] bone's connected to the $bp[name] bone");
if (tracePart($body, $bp))
$numcat++;
}
}
}
if (!$found)
warning("Body part $part[id] could not find [CATEGORY:$part[CON_CAT]] body part to connect to!");
}
if (isset($part['CONTYPE']))
{
$types++;
$found = FALSE;
foreach ($body as $bp)
{
if (isset($bp[$part['CONTYPE']]))
{
$found = TRUE;
if ($numtype)
verbose("...and the $part[name] bone's connected to the $bp[name] bone");
else verbose("The $part[name] bone's connected to the $bp[name] bone");
if (tracePart($body, $bp))
$numtype++;
}
}
if (!$found)
warning("Body part $part[id] could not find [$part[CONTYPE]] body part to connect to!");
}
if ($types > 1)
warning("Body part $part[id] has multiple connections?");
return ($numcon + $numcat + $numtype) > 0;
}
function parseBody ($name, $body)
{
global $bodies;
verbose("Parsing body of creature $name");
array_shift($body);
$parts = array();
foreach ($body as $b)
{
if (!isset($bodies[$b]))
{
warning("Creature $name attempting to add nonexistent body $b!");
continue;
}
verbose("Creature $name uses the BODY group '$b'");
foreach ($bodies[$b] as $part)
{
verbose("That includes the '$part[name]' ($part[id])");
if (isset($parts[$part['id']]))
{
$dup = $parts[$part['id']];
verbose("...but that's got the same ID as the $dup[name]!");
warning("Creature $name includes multiple instances of body part $part[id]!");
}
}
$parts = array_merge($parts, $bodies[$b]);
}
$upper = array();
foreach ($parts as $id => $part)
{
if (isset($part['UPPERBODY']))
$upper[] = $id;
}
if (count($upper) == 0)
{
notice("Creature $name has no upper body, skipping.");
return;
}
if (count($upper) > 1)
{
notice("Creature $name has more than one upper body, skipping.");
return;
}
verbose("Creature $name has ". count($parts) ." body parts, starting at $upper[0].");
foreach ($parts as $id => $part)
{
if (!tracePart($parts, $part))
notice("Creature $name body part '$part[name]' is unconnected!");
}
verbose('');
}
$bodies = array();
foreach (glob("raw/objects/*.txt") as $filename)
{
$in = fopen($filename, "r");
if (!$in)
continue;
$token = readToken($in);
if (($token) && ($token[0] == 'OBJECT') && ($token[1] == 'BODY'))
readBodies($bodies, $in);
fclose($in);
}
if (!count($bodies))
error("unable to locate any body part definitions - please run this from the game's root folder (or from a region folder)");
foreach (glob("raw/objects/*.txt") as $filename)
{
$in = fopen($filename, "r");
if (!$in)
continue;
$token = readToken($in);
if (($token) && ($token[0] == 'OBJECT') && ($token[1] == 'CREATURE'))
{
$creature = '';
while (1)
{
$token = readToken($in);
if (!$token)
break;
if ($token[0] == 'CREATURE')
$creature = $token[1];
if (($creature != '') && ($token[0] == 'BODY'))
{
if (in_array($filter, array($creature, 'all')))
parseBody($creature, $token);
}
}
}
fclose($in);
}
?>