v50 Steam/Premium information for editors
  • v50 information can now be added to pages in the main namespace. v0.47 information can still be found in the DF2014 namespace. See here for more details on the new versioning policy.
  • Use this page to report any issues related to the migration.
This notice may be cached—the current version can be found here.

Difference between revisions of "User:Quietust/parsebody.php"

From Dwarf Fortress Wiki
Jump to navigation Jump to search
(Update to support multiple body part definition files)
m (fix bug with CON_CAT/CONTYPE body parts not finding their way to the upper body and displaying the wrong error)
Line 124: Line 124:
 
if (isset($part['UPPERBODY']))
 
if (isset($part['UPPERBODY']))
 
{
 
{
verbose("-");
+
verbose("The $part[name] bone is the upper body");
 
return TRUE;
 
return TRUE;
 
}
 
}
 
$types = 0;
 
$types = 0;
$found = FALSE;
 
 
$numcon = $numcat = $numtype = 0;
 
$numcon = $numcat = $numtype = 0;
 
if (isset($part['CON']))
 
if (isset($part['CON']))
Line 146: Line 145:
 
{
 
{
 
$types++;
 
$types++;
 +
$found = FALSE;
 
foreach ($body as $bp)
 
foreach ($body as $bp)
 
{
 
{
Line 152: Line 152:
 
if ($part['CON_CAT'] == $bp['CATEGORY'])
 
if ($part['CON_CAT'] == $bp['CATEGORY'])
 
{
 
{
 +
$found = TRUE;
 
if ($numcat)
 
if ($numcat)
 
verbose("...and the $part[name] bone's connected to the $bp[name] bone");
 
verbose("...and the $part[name] bone's connected to the $bp[name] bone");
Line 160: Line 161:
 
}
 
}
 
}
 
}
if (!$numcat)
+
if (!$found)
 
warning("Body part $part[id] could not find [CATEGORY:$part[CON_CAT]] body part to connect to!");
 
warning("Body part $part[id] could not find [CATEGORY:$part[CON_CAT]] body part to connect to!");
 
}
 
}
Line 166: Line 167:
 
{
 
{
 
$types++;
 
$types++;
 +
$found = FALSE;
 
foreach ($body as $bp)
 
foreach ($body as $bp)
 
{
 
{
 
if (isset($bp[$part['CONTYPE']]))
 
if (isset($bp[$part['CONTYPE']]))
 
{
 
{
 +
$found = TRUE;
 
if ($numtype)
 
if ($numtype)
 
verbose("...and the $part[name] bone's connected to the $bp[name] bone");
 
verbose("...and the $part[name] bone's connected to the $bp[name] bone");
Line 177: Line 180:
 
}
 
}
 
}
 
}
if (!$numtype)
+
if (!$found)
 
warning("Body part $part[id] could not find [$part[CONTYPE]] body part to connect to!");
 
warning("Body part $part[id] could not find [$part[CONTYPE]] body part to connect to!");
 
}
 
}

Revision as of 21:07, 27 January 2012

<?
$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");
		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 = 0;
		while (1)
		{
			$token = readToken($in);
			if (!$token)
				break;
			if ($token[0] == 'CREATURE')
				$creature = $token[1];
			if ($token[0] == 'BODY')
			{
				if (in_array($filter, array($creature, 'all')))
					parseBody($creature, $token);
			}
		}
	}
	fclose($in);
}
?>