SITE ANNOUNCEMENTS:

User:Quietust/parsebody.php

From Dwarf Fortress Wiki
< User:Quietust
Revision as of 21:13, 27 January 2012 by Quietust (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
<?
$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);
}
?>
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox
Advertisement