Source code for TomeNET monster search
common.inc.php
<?php
//if (ob_get_level()) ob_end_clean();
//ob_start('ob_gzhandler');
$colors_hex = array(
'd' => '#000000', // black
'D' => '#747474', // dark
's' => '#9D9D9D', // slate
'W' => '#D7D7D7', // white
'w' => '#FFF', // bright white
'b' => '#0000FF', // blue
'g' => '#009D44', // green
'r' => '#D70000', // red
'u' => '#8D6600', // umber
'y' => '#FFFF00', // yellow
'B' => '#00FFFF', // light blue
'G' => '#00FF00', // light green
'R' => '#FF0000', // pink
'U' => '#C79D55', // light umber
'o' => '#FF8D00', // orange
'v' => '#AF00FF', // violet
'a' => '#AF00FF', // acidic, monsters of bad luck (FIXME: animate)
'I' => '#AF00FF', // new color for disenchantment / invulnerability (FIXME: animate)
'f' => '#D70000', // fire (red) (FIXME: animate)
'p' => '#00FF00', // poison (light green) (FIXME: animate)
'M' => '#FFF', // manashield (white for now) (FIXME: animate)
'L' => '#FFFF00', // lite (candlebearer) (FIXME: animate)
'c' => '#FFF', // cold (will o' wisp) (FIXME: animate)
'e' => '#00FFFF', // electric (living lightning) (FIXME: animate)
'Z' => '#D70000', // ember (FIXME: animate)
'K' => '#009D44', // unbreath (FIXME)
'C' => '#C79D55', // confusion (FIXME)
'q' => '#9D9D9D', // inertia (FIXME)
'A' => '#747474', // darkness (FIXME)
'S' => '#FFFF00', // sound (FIXME)
'k' => '#D70000', // nuke (FIXME)
);
$colors_name = array(
'd' => 'black',
'D' => 'dark',
's' => 'slate',
'W' => 'white',
'w' => 'bright white',
'b' => 'blue',
'g' => 'green',
'r' => 'red',
'u' => 'umber',
'y' => 'yellow',
'B' => 'light blue',
'G' => 'light green',
'R' => 'light red',
'U' => 'light umber',
'o' => 'orange',
'v' => 'violet',
'a' => 'acidic',
'I' => 'invulnerability',
'f' => 'fiery',
'p' => 'poisony',
'M' => 'manashieldy',
'L' => 'lite',
'c' => 'cold',
'e' => 'electric',
'Z' => 'ember',
'K' => 'unbreath',
'C' => 'confusion',
'q' => 'inertia',
'A' => 'darkness',
'S' => 'sound',
'k' => 'nuke',
);
$monster_types = array(
'NONEBAND',
'BASEANGBAND',
'ZANGBAND',
'CTHANGBAND',
'JOKEANGBAND',
'PERNANGBAND',
'BLUEBAND',
);
$monster_types_desc = array(
'None',
'Base',
'Zangband',
'Cthulhu',
'Joke',
'Pern',
'Blue',
);
function get_hex_color($m) {
return($GLOBALS['colors_hex'][$m['color']]);
}
// Old code
function get_type($m) {
if (array_search('BASEANGBAND', $m['flags']) !== FALSE) return 'Base';
elseif (array_search('ZANGBAND', $m['flags']) !== FALSE) return 'Zangband';
elseif (array_search('CTHANGBAND', $m['flags']) !== FALSE) return 'Cthulhu';
elseif (array_search('JOKEANGBAND', $m['flags']) !== FALSE) return 'Joke';
elseif (array_search('PERNANGBAND', $m['flags']) !== FALSE) return 'Pern';
elseif (array_search('BLUEBAND', $m['flags']) !== FALSE) return 'Blue';
else return '?';
}
$monster_bg_colors_by_type = array(
'#FFF',
'#B7FFB4', // BASEANGBAND
'#FFFFB4', // ZANGBAND
'#B4FFF6', // CTHANGBAND
'#FFE6B4', // JOKEANGBAND
'#FFB4E0', // PERNANGBAND
'#B4B9FF', // BLUEBAND
);
// Old code
function get_result_bg_color($m) {
if (array_search('BASEANGBAND', $m['flags']) !== FALSE) return '#B7FFB4';
if (array_search('ZANGBAND', $m['flags']) !== FALSE) return '#FFFFB4';
if (array_search('CTHANGBAND', $m['flags']) !== FALSE) return '#B4FFF6';
if (array_search('JOKEANGBAND', $m['flags']) !== FALSE) return '#FFE6B4';
if (array_search('PERNANGBAND', $m['flags']) !== FALSE) return '#FFB4E0';
if (array_search('BLUEBAND', $m['flags']) !== FALSE) return '#B4B9FF';
return '#FFF';
}
function is_unique($m) {
if (array_search('UNIQUE', $m['flags']) !== FALSE) return 'Yes';
return 'No';
}
function count_hp($m) {
$d = explode('d', $m['hp']);
if (array_search('FORCE_MAXHP', $m['flags']) === FALSE) {
$hp = '~' . ($d[0] * ($d[1] + 1) / 2);
} else {
$hp = $d[0] * $d[1];
}
return($hp);
}
function count_hp_no_tilde($m) {
$d = explode('d', $m['hp']);
if (array_search('FORCE_MAXHP', $m['flags']) === FALSE) {
$hp = $d[0] * ($d[1] + 1) / 2;
} else {
$hp = $d[0] * $d[1];
}
return($hp);
}
function parse_gpc($a) {
// Fix for PHP 8
return($a);
if (get_magic_quotes_gpc()) {
return(stripslashes($a));
} else {
return($a);
}
}
// Old compability code
if (!function_exists('stripos')) {
function stripos($a, $b) {
return(strpos(strtolower($a), strtolower($b)));
}
}
?>
flags.php
<?php
$flags = array('AI_ANNOY', 'AI_SPECIAL', 'ALLOW_RUNNING', 'ANIMAL', 'AQUATIC', 'ASTAR', 'ATTR_ANY', 'ATTR_BASE', 'ATTR_BNW', 'ATTR_CLEAR', 'ATTR_MULTI', 'AURA_COLD', 'AURA_ELEC', 'AURA_FIRE', 'AVOID_PERMAWALLS', 'BASEANGBAND', 'BASH_DOOR', 'BLUEBAND', 'CAN_FLY', 'CAN_SPEAK', 'CAN_SWIM', 'CHAR_CLEAR', 'CHAR_MULTI', 'COLD_BLOOD', 'CTHANGBAND', 'DEATH_ORB', 'DEMON', 'DG_CURSE', 'DISBELIEVE', 'DRAGON', 'DRAGONRIDER', 'DROP_1', 'DROP_1D2', 'DROP_2D2', 'DROP_3D2', 'DROP_4D2', 'DROP_60', 'DROP_90', 'DROP_CHOSEN', 'DROP_CORPSE', 'DROP_GOOD', 'DROP_GREAT', 'DROP_SKELETON', 'DROP_USEFUL', 'DUN_9', 'ELDRITCH_HORROR', 'EMPTY_MIND', 'ESCORT', 'ESCORTS', 'EVIL', 'FEMALE', 'FORCE_DEPTH', 'FORCE_MAXHP', 'FORCE_SLEEP', 'FRIEND', 'FRIENDS', 'GENO_NO_THIN', 'GENO_PERSIST', 'GIANT', 'GOOD', 'HAS_EGG', 'HAS_LITE', 'HURT_LITE', 'HURT_ROCK', 'IMPRESSED', 'IM_ACID', 'IM_COLD', 'IM_ELEC', 'IM_FIRE', 'IM_POIS', 'IM_PSI', 'IM_TELE', 'IM_WATER', 'INVISIBLE', 'JOKEANGBAND', 'KILL_BODY', 'KILL_ITEM', 'KILL_TREES', 'KILL_WALL', 'MALE', 'MIMIC', 'MORTAL', 'MOVE_BODY', 'MULTIPLY', 'NAZGUL', 'NETHER_REALM', 'NEUTRAL', 'NEVER_ACT', 'NEVER_BLOW', 'NEVER_MOVE', 'NONLIVING', 'NO_AUTORET', 'NO_BLOCK', 'NO_CONF', 'NO_CUT', 'NO_DEATH', 'NO_ESCORT', 'NO_FEAR', 'NO_NEST', 'NO_SLEEP', 'NO_STUN', 'NO_TARGET', 'ONLY_DEPTH', 'ONLY_GOLD', 'ONLY_ITEM', 'OOD_10', 'OPEN_DOOR', 'ORC', 'PASS_WALL', 'PERNANGBAND', 'PET', 'PLURAL', 'POSSESSOR', 'POWERFUL', 'PSEUDO_UNIQUE', 'RAND_25', 'RAND_5', 'RAND_50', 'REFLECTING', 'REGENERATE', 'RES_ACID', 'RES_CHAOS', 'RES_COLD', 'RES_DARK', 'RES_DISE', 'RES_ELEC', 'RES_FIRE', 'RES_LITE', 'RES_MANA', 'RES_NETH', 'RES_NEXU', 'RES_PLAS', 'RES_POIS', 'RES_PSI', 'RES_SHARDS', 'RES_SOUND', 'RES_TELE', 'RES_TIME', 'RES_WATE', 'ROAMING', 'SHAPECHANGER', 'SMART', 'SPECIAL_GENE', 'SPIDER', 'STUPID', 'SUSCEP_ACID', 'SUSCEP_COLD', 'SUSCEP_ELEC', 'SUSCEP_FIRE', 'S_LOWEXP', 'TAKE_ITEM', 'TROLL', 'UNDEAD', 'UNIQUE', 'WEIRD_MIND', 'WILD_DESERT', 'WILD_EASY', 'WILD_GRASS', 'WILD_MOUNTAIN', 'WILD_OCEAN', 'WILD_ONLY', 'WILD_SHORE', 'WILD_SWAMP', 'WILD_TOO', 'WILD_TOWN', 'WILD_VOLCANO', 'WILD_WASTE', 'WILD_WOOD', 'WYRM_PROTECT', 'ZANGBAND');
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><title>List of flags | TomeNET monster search</title></head><body bgcolor=#ffffff><h1>List of flags used in r_info.txt</h1><table border=0 cellpadding=0 cellspacing=1 width=100%><tr>
<?php
for ($i = 0, $n = count($flags); $i < $n; ++$i)
{
echo('<td>' . $flags[$i] . '</td>');
if (($i + 1) % 3 == 0)
{
echo ('</tr><tr>');
}
}
?>
</tr></table>
<p><a href="javascript: history.go(-1)">Back</a></p>
</body></html>
index.php
<?php
$r_info_file = 'r_info.txt.gz';
require('common.inc.php');
// Set the timezone for date()
date_default_timezone_set('UTC');
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>TomeNET monster search</title>
<link rel="stylesheet" href="monsters.css" type="text/css">
</head>
<body>
<h1>TomeNET monster search</h1>
<p><form action="<?php echo(htmlspecialchars(basename(__FILE__))); ?>" name="s" method="GET">
<?php
$get_values = array(
'name', 'char', 'color', 'level_min', 'level_max', 'hp_min', 'hp_max', 'spell_chance_min',
'spell_chance_max', 'spells', 'flags', 'description'
);
$htmlvalues = array();
// Try to load any previously submitted values
foreach ($get_values as $name) {
if (isset($_GET[$name])) {
$htmlvalues[$name] = htmlspecialchars(parse_gpc($_GET[$name]));
} else {
$htmlvalues[$name] = '';
}
}
echo('<b>Name:</b> <input type="text" name="name" id="monster_name" autofocus value="' . $htmlvalues['name'] . '">
<b>Character:</b> <input type="text" name="char" size="2" maxlength="1" value="' . $htmlvalues['char'] . '">
<b>Color:</b> <input type="text" name="color" size="2" maxlength="1" value="' . $htmlvalues['color'] . '"><br><br>');
// Default ticks for the checkboxes
if (!isset($_GET['type']) || !is_array($_GET['type'])) {
$_GET['type'] = array('base', 'zang', 'cthulhu', 'pern', 'blue', 'none');
}
$type_base = in_array('base', $_GET['type']);
$type_zang = in_array('zang', $_GET['type']);
$type_cthulhu = in_array('cthulhu', $_GET['type']);
$type_pern = in_array('pern', $_GET['type']);
$type_blue = in_array('blue', $_GET['type']);
$type_joke = in_array('joke', $_GET['type']);
$type_none = in_array('none', $_GET['type']);
echo("<b>Monster type:</b>\n");
if ($type_base) echo('<input type="checkbox" name="type[]" id="base" value="base" CHECKED>');
else echo('<input type="checkbox" name="type[]" id="base" value="base">');
echo('<label for="base"><span style="background-color: #B7FFB4">Base</span></label>');
if ($type_zang) echo('<input type=checkbox name="type[]" id="zang" value="zang" CHECKED>');
else echo('<input type=checkbox name="type[]" id="zang" value="zang">');
echo('<label for="zang"><span style="background-color: #FFFFB4">Zangband</span></label>');
if ($type_cthulhu) echo('<input type=checkbox name="type[]" id="cthulhu" value="cthulhu" CHECKED>');
else echo('<input type=checkbox name="type[]" id="cthulhu" value="cthulhu">');
echo('<label for="cthulhu"><span style="background-color: #B4FFF6">Cthulhu</span></label>');
if ($type_pern) echo('<input type=checkbox name="type[]" id="pern" value="pern" CHECKED>');
else echo('<input type=checkbox name="type[]" id="pern" value="pern">');
echo('<label for="pern"><span style="background-color: #FFB4E0">Pernband</span></label>');
if ($type_blue) echo('<input type=checkbox name="type[]" id="blue" value="blue" CHECKED>');
else echo('<input type=checkbox name="type[]" id="blue" value="blue">');
echo('<label for="blue"><span style="background-color: #B4B9FF">Blueband</span></label>');
if ($type_joke) echo('<input type=checkbox name="type[]" id="joke" value="joke" CHECKED>');
else echo('<input type=checkbox name="type[]" id="joke" value="joke">');
echo('<label for="joke"><span style="background-color: #FFE6B4">Joke</span></label>');
if ($type_none) echo('<input type=checkbox name="type[]" id="none" value="none" CHECKED>');
else echo('<input type=checkbox name="type[]" id="none" value="none">');
echo('<label for="none"><span style="background-color: #FFE6B4">None</span></label><br><br>');
echo('<table border="0" cellpadding="0" cellspacing="2">
<col>
<col width="30">
<col>
<col width="30">
<col>
<tr>
<td><input type="text" name="level_min" size="5" maxlength="3" value="' . $htmlvalues['level_min'] . '"></td>
<td align="center">≤</td>
<td align="center"><b>Level</b></td>
<td align="center">≤</td><td><input type="text" name="level_max" size="5" maxlength="3" value="' . $htmlvalues['level_max'] . '"></td>
</tr>
<tr>
<td><input type="text" name="hp_min" size="5" maxlength="5" value="' . $htmlvalues['hp_min'] . '"></td>
<td align="center">≤</td>
<td align="center"><b>HP</b></td>
<td align="center">≤</td>
<td><input type="text" name="hp_max" size="5" maxlength="5" value="' . $htmlvalues['hp_max'] . '"></td>
</tr>
<tr>
<td><input type="text" name="spell_chance_min" size="5" maxlength="2" value="' . $htmlvalues['spell_chance_min'] . '"></td>
<td align="center">≤</td>
<td align="center"><b>1_IN_x</b></td>
<td align="center">≤</td>
<td><input type="text" name="spell_chance_max" size="5" maxlength="2" value="' . $htmlvalues['spell_chance_max'] . '"><br></td>
</tr>
</table>
<table border="0" cellpadding="0" cellspacing="2">
<col width="100">
<col>
<tr>
<td><b>Spells:</b></td>
<td><input type="text" name="spells" value="' . $htmlvalues['spells'] . '" size="40"></td>
</tr>
<tr>
<td> </td>
<td><small>(e.g. BR_NETH (breaths nether) or !S_HI_DRAGON (doesn\'t summon high dragons)) (<a href="spells.php">list of spells</a>)</small></td>
</tr>
<tr>
<td><b>Flags:</b></td>
<td><input type="text" name="flags" value="' . $htmlvalues['flags'] . '" size="40"></td>
</tr>
<tr>
<td> </td>
<td><small>(e.g. ATTR_MULTI (multi-colored) or !UNIQUE (not unique)) (<a href="flags.php">list of flags</a>)</small></td>
</tr>
<tr>
<td><b>Description:</b></td>
<td><input type="text" name="description" value="' . $htmlvalues['description'] . '" size="40"></td>
</tr>
</table>');
?>
<input type="submit" name="submit" value="Search">
<input type="reset" name="reset" value="Reset">
</form>
<p><a href="../index.php">Back to mikaelh's TomeNET site</a></p>
<?php
/* Flush before loading the monsters */
flush();
/* Load the monsters (takes some time ...) */
require('parser.php');
function filter_monsters_by_name_contains_string(&$monsters, $value) {
$parts = explode(' ', $value);
foreach ($monsters as &$monster) {
$name = $monster['name'];
foreach ($parts as $part) {
if (stripos($name, $part) === FALSE) {
$monster['matches'] = FALSE;
continue(2);
}
}
}
}
function filter_monsters_by_string_match(&$monsters, $key, $value) {
foreach ($monsters as &$monster) {
if ($monster[$key] != $value) {
$monster['matches'] = FALSE;
}
}
}
function filter_monsters_by_type(&$monsters, $allowed_types_bitmask) {
foreach ($monsters as &$monster) {
if (!($monster['type_bit'] & $allowed_types_bitmask)) {
$monster['matches'] = FALSE;
}
}
}
function filter_monsters_by_greater_or_equal(&$monsters, $key, $value) {
foreach ($monsters as &$monster) {
if ($monster[$key] < $value) {
$monster['matches'] = FALSE;
}
}
}
function filter_monsters_by_less_or_equal(&$monsters, $key, $value) {
foreach ($monsters as &$monster) {
if ($monster[$key] > $value) {
$monster['matches'] = FALSE;
}
}
}
function filter_monsters_by_hp_greater_or_equal(&$monsters, $value) {
foreach ($monsters as &$monster) {
if (count_hp_no_tilde($monster) < $value) {
$monster['matches'] = FALSE;
}
}
}
function filter_monsters_by_hp_less_or_equal(&$monsters, $value) {
foreach ($monsters as &$monster) {
if (count_hp_no_tilde($monster) > $value) {
$monster['matches'] = FALSE;
}
}
}
function filter_monsters_by_spells(&$monsters, $spells) {
foreach ($monsters as &$monster) {
foreach ($spells as $spell) {
if ($spell[0] == '!') {
if (in_array(substr($spell, 1), $monster['spells'])) {
$monster['matches'] = FALSE;
continue(2);
}
} else {
if (!in_array($spell, $monster['spells'])) {
$monster['matches'] = FALSE;
continue(2);
}
}
}
}
}
function filter_monsters_by_flags(&$monsters, $flags) {
foreach ($monsters as &$monster) {
foreach ($flags as $flag) {
if ($flag[0] == '!') {
if (in_array(substr($flag, 1), $monster['flags'])) {
$monster['matches'] = FALSE;
continue(2);
}
} else {
if (!in_array($flag, $monster['flags'])) {
$monster['matches'] = FALSE;
continue(2);
}
}
}
}
}
function filter_monsters_by_desc_contains_string(&$monsters, $value) {
$parts = explode(' ', $value);
foreach ($monsters as &$monster) {
$desc = $monster['description'];
foreach ($parts as $part) {
if (stripos($desc, $part) === FALSE) {
$monster['matches'] = FALSE;
continue(2);
}
}
}
}
function get_search_results($monsters) {
global $monster_types_bits;
$start = microtime(TRUE);
// Determine which checkboxes have been ticked
if (isset($_GET['type'])) {
$GET_type = $_GET['type'];
} else {
$GET_type = array();
}
if (isset($_GET['name']) && strlen(trim($_GET['name'])) > 0) {
filter_monsters_by_name_contains_string($monsters, trim(parse_gpc($_GET['name'])));
}
if (isset($_GET['char']) && strlen(trim($_GET['char'])) > 0) {
filter_monsters_by_string_match($monsters, 'symbol', substr(trim(parse_gpc($_GET['char'])), 0, 1));
}
if (isset($_GET['color']) && strlen(trim($_GET['color'])) > 0) {
filter_monsters_by_string_match($monsters, 'color', substr(trim(parse_gpc($_GET['color'])), 0, 1));
}
if (count($GET_type) > 0) {
$allowed_types_bitmask = 0;
if (in_array('base', $GET_type)) $allowed_types_bitmask |= $monster_types_bits['BASEANGBAND'];
if (in_array('zang', $GET_type)) $allowed_types_bitmask |= $monster_types_bits['ZANGBAND'];
if (in_array('cthulhu', $GET_type)) $allowed_types_bitmask |= $monster_types_bits['CTHANGBAND'];
if (in_array('pern', $GET_type)) $allowed_types_bitmask |= $monster_types_bits['PERNANGBAND'];
if (in_array('blue', $GET_type)) $allowed_types_bitmask |= $monster_types_bits['BLUEBAND'];
if (in_array('joke', $GET_type)) $allowed_types_bitmask |= $monster_types_bits['JOKEANGBAND'];
if (in_array('none', $GET_type)) $allowed_types_bitmask |= $monster_types_bits['NONEBAND'];
filter_monsters_by_type($monsters, $allowed_types_bitmask);
}
if (isset($_GET['level_min']) && strlen(trim($_GET['level_min'])) > 0) {
$min_level = (int) $_GET['level_min'];
filter_monsters_by_greater_or_equal($monsters, 'depth', $min_level);
}
if (isset($_GET['level_max']) && strlen(trim($_GET['level_max'])) > 0) {
$max_level = (int) $_GET['level_max'];
filter_monsters_by_less_or_equal($monsters, 'depth', $max_level);
}
if (isset($_GET['hp_min']) && strlen(trim($_GET['hp_min'])) > 0) {
$min_hp = (int) $_GET['hp_min'];
filter_monsters_by_hp_greater_or_equal($monsters, $min_hp);
}
if (isset($_GET['hp_max']) && strlen(trim($_GET['hp_max'])) > 0) {
$max_hp = (int) $_GET['hp_max'];
filter_monsters_by_hp_less_or_equal($monsters, $max_hp);
}
if (isset($_GET['spell_chance_min']) && strlen(trim($_GET['spell_chance_min'])) > 0) {
$min_spell_chance = (int) $_GET['spell_chance_min'];
filter_monsters_by_greater_or_equal($monsters, 'spell_chance', $min_spell_chance);
}
if (isset($_GET['spell_chance_max']) && strlen(trim($_GET['spell_chance_max'])) > 0) {
$max_spell_chance = (int) $_GET['spell_chance_max'];
filter_monsters_by_less_or_equal($monsters, 'spell_chance', $max_spell_chance);
}
if (isset($_GET['spells']) && strlen(trim($_GET['spells'])) > 0) {
$spells = explode(' ', trim(parse_gpc($_GET['spells'])));
$spells_uppercased = array();
foreach ($spells as $spell) {
$spells_uppercased[] = strtoupper(trim($spell));
}
filter_monsters_by_spells($monsters, $spells_uppercased);
}
if (isset($_GET['flags']) && strlen(trim($_GET['flags'])) > 0) {
$flags = explode(' ', trim(parse_gpc($_GET['flags'])));
$flags_uppercased = array();
foreach ($flags as $flag) {
$flags_uppercased[] = strtoupper(trim($flag));
}
filter_monsters_by_flags($monsters, $flags_uppercased);
}
if (isset($_GET['description']) && strlen(trim($_GET['description'])) > 0) {
filter_monsters_by_desc_contains_string($monsters, trim($_GET['description']));
}
$results = array();
foreach ($monsters as $monster) {
if ($monster['matches']) {
$results[] = $monster;
}
}
$end = microtime(TRUE);
//echo(($end - $start) * 1000 . " milliseconds");
return $results;
}
function show_search_results($results) {
$monster_bg_colors_by_type = $GLOBALS['monster_bg_colors_by_type'];
$start = microtime(TRUE);
$num_results = count($results);
echo('<p><b>Number of results: ' . $num_results . "</b></p>\n");
// Split the list into 3 columns
$n_rows = ceil($num_results / 3);
$num_rows = array($n_rows, $n_rows, $n_rows);
if ($num_results % 3 == 1) {
// Columns 2 and 3 will be shorter
$num_rows[1]--;
$num_rows[2]--;
} elseif ($num_results % 3 == 2) {
// Column 3 will be shorter
$num_rows[2]--;
}
$col_1 = array();
$col_2 = array();
$col_3 = array();
for ($i = 0, $n = $num_rows[0]; $i < $n; $i++) {
$col_1[] = $results[$i];
}
for ($n = $num_rows[0] + $num_rows[1]; $i < $n; $i++) {
$col_2[] = $results[$i];
}
for ($n = $num_rows[0] + $num_rows[1] + $num_rows[2]; $i < $n; $i++) {
$col_3[] = $results[$i];
}
$cols = array($col_1, $col_2, $col_3);
$output = "<p><table border=\"0\" cellpadding=\"0\" cellspacing=\"1\">\n" .
"<col width=\"20\"><col width=\"300\"><col width=\"40\">\n" .
"<col width=\"20\"><col width=\"300\"><col width=\"40\">\n" .
"<col width=\"20\"><col width=\"300\"><col width=\"40\">\n" .
"<tr><th> </th><th><b>Name</b></th><th><b>Lvl</b></th><th> </th><th><b>Name</b></th><th><b>Lvl</b></th><th> </th><th><b>Name</b></th><th><b>Lvl</b></th></tr>\n";
$n = count($results);
if ($n) $output .= "<tr>\n";
for ($i = 0; $i < $n; ++$i) {
$result = $cols[$i % 3][floor($i / 3)];
$output .= '<td class="symbol" style="color: ' . get_hex_color($result) . '">' . $result['symbol'] . '</td><td style="background-color: ' .
$monster_bg_colors_by_type[$result['type']] . '"><a href="monster.php?' . $result['number'] . '">' . htmlspecialchars($result['name']) . '</a></td><td>' . $result['depth'] . "</td>\n";
if (($i + 1) % 3 == 0) {
$output .= "</tr><tr>\n";
}
}
if ($n) $output .= "</tr>\n";
$output .= "</table></p>\n";
echo($output);
$end = microtime(TRUE);
//echo(($end - $start) * 1000 . " milliseconds");
}
$results = get_search_results($monsters);
show_search_results($results);
?>
<p style="font-size: 0.75em">TomeNET monster search v. 0.1.7<br>
r_info.txt was last updated on <?php echo(date("d.m.Y", filemtime($r_info_file))); ?>.<br>
<a href="source.php">Source code</a>
<script>
document.getElementById('monster_name').focus();
</script>
</body></html>
makeflags.php
<?php
require('parser.php');
$flags = array();
foreach ($monsters as $monster)
{
foreach ($monster['flags'] as $flag)
{
if (!in_array($flag, $flags))
{
$flags[] = $flag;
}
}
}
sort($flags);
echo("\$flags = array('" . implode("', '", $flags) . "');\n");
?>
makespells.php
<?php
require('parser.php');
$spells = array();
foreach ($monsters as $monster)
{
foreach ($monster['spells'] as $spell)
{
if (!in_array($spell, $spells))
{
$spells[] = $spell;
}
}
}
sort($spells);
echo("\$spells = array('" . implode("', '", $spells) . "');\n");
?>
monster.php
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="stylesheet" href="monsters.css" type="text/css">
<?php
/* Flush the link to stylesheet before loading monsters */
flush();
require('common.inc.php');
require('parser.php');
function get_depth($l) {
return(($l * 50) . 'ft');
}
function symbol_info($m) {
if (array_search('SHAPECHANGER', $m['flags']) !== FALSE) return 'shapechanger';
if (array_search('CHAR_CLEAR', $m['flags']) !== FALSE) return 'absorbs symbol';
return 'Symbol ' . $m['symbol'];
}
function color_info($m) {
if (array_search('ATTR_MULTI', $m['flags']) !== FALSE && array_search('ATTR_ANY', $m['flags']) !== FALSE) return 'truly multi-colored';
if (array_search('ATTR_MULTI', $m['flags']) !== FALSE) return 'multi-colored ' . $m['color'];
if (array_search('ATTR_CLEAR', $m['flags']) !== FALSE) return 'absorbs color';
return 'Color ' . $m['color'];
}
function show_info_html($m) {
$monster_types_desc = $GLOBALS['monster_types_desc'];
echo("<div class=\"monster\">\n");
echo("<h1>" . $m['name'] . "</h1>\n");
echo("<span class=\"header\">Id:</span> " . $m['number']);
echo(" <span class=\"header\">Name:</span> " . $m['name'] . " <span class=\"symbol\" style=\"color: " . get_hex_color($m) . "\"> " . $m['symbol'] . " </span> (" . symbol_info($m) . ", " . color_info($m) .")<br>\n");
// Some monsters lack a description
echo("<span class=\"header\">Description:</span> " . $m['description'] . "<br>\n");
echo("<span class=\"header\">Type:</span> " . $monster_types_desc[$m['type']]);
echo(" <span class=\"header\">Unique:</span> " . is_unique($m) . "<br>\n");
echo("<span class=\"header\">HP:</span> " . count_hp($m) . " (" . $m['hp'] . ")");
echo(" <span class=\"header\">AC:</span> " . $m['ac']);
echo(" <span class=\"header\">Experience:</span> " . $m['exp']);
echo(" <span class=\"header\">Speed:</span> " . $m['speed'] . "<br>\n");
echo("<span class=\"header\">Depth:</span> " . $m['depth'] . " (" . get_depth($m['depth']) . ")");
echo(" <span class=\"header\">Rarity:</span> " . $m['rarity']);
echo(" <span class=\"header\">Vision:</span> " . $m['vision']);
echo(" <span class=\"header\">Alertness:</span> " . $m['alertness'] . "<br>\n");
echo("<span class=\"header\">Body:</span><br>");
echo("<div class=\"sub\">\n");
echo("<span class=\"header\">Weight:</span> " . $m['weight']);
echo(" <span class=\"header\">Weapons:</span> " . $m['weapons']);
echo(" <span class=\"header\">Torso:</span> " . $m['torso']);
echo(" <span class=\"header\">Arm:</span> " . $m['arms']);
echo(" <span class=\"header\">Finger:</span> " . $m['finger']);
echo(" <span class=\"header\">Head:</span> " . $m['head']);
echo(" <span class=\"header\">Leg:</span> " . $m['leg'] . "<br>\n");
echo("</div>\n");
echo("<span class=\"header\">Objects:</span><br>\n");
echo("<div class=\"sub\">\n");
echo("<span class=\"header\">Treasure:</span> " . $m['treasure']);
echo(" <span class=\"header\">Combat:</span> " . $m['combat']);
echo(" <span class=\"header\">Magic:</span> " . $m['magic']);
echo(" <span class=\"header\">Tool:</span> " . $m['tool'] . "<br>\n");
echo("</div>\n");
echo("<span class=\"header\">Attack methods:</span><br>\n");
foreach ($m['attacks'] as $a) {
echo("\t<div style=\"padding-left: 1em;\">");
echo($a['method'] . ": ");
echo($a['effect']);
if (!empty($a['damage'])) echo(" (" . $a['damage'] . ")");
echo("</div>\n");
}
if ($m['spell_chance'] != 0) {
echo("<span class=\"header\">Spell chance:</span> 1 spell every " . $m['spell_chance'] . " turns (1_IN_" . $m['spell_chance'] . ")<br>\n");
}
echo("<span class=\"header\">Spells (and breaths, arrows or missiles): (" . count($m['spells']) . ")</span><br>\n");
echo("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n");
echo("\t<col width=\"200\">\n");
echo("\t<col width=\"200\">\n");
echo("\t<col width=\"200\">\n");
echo("\t<tr>\n");
$i = 0;
foreach ($m['spells'] as $s) {
echo("\t\t<td>" . $s . "</td>\n");
if (!(++$i % 3)) echo("\t</tr>\n\t<tr>\n");
}
while ($i % 3) {
echo("\t\t<td> </td>\n");
++$i;
}
echo("\t</tr>\n</table>\n");
echo("<span class=\"header\">Flags: (" . count($m['flags']) . ")</span><br>\n");
echo("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n");
echo("\t<col width=\"200\">\n");
echo("\t<col width=\"200\">\n");
echo("\t<col width=\"200\">\n");
echo("\t<tr>\n");
$i = 0;
foreach ($m['flags'] as $f) {
echo("\t\t<td>" . $f . "</td>\n");
if (!(++$i % 3)) echo("\t</tr>\n\t<tr>\n");
}
while ($i % 3) {
echo("\t\t<td> </td>\n");
++$i;
}
echo("\t</tr>\n</table>\n");
echo("</div>\n");
}
if (array_key_exists($_SERVER['QUERY_STRING'], $monsters)) {
$monster = $monsters[$_SERVER['QUERY_STRING']];
?>
<title><?php echo(htmlentities($monster['name'])) ?> | TomeNET monster search</title>
</head>
<body>
<?php show_info_html($monster); ?>
<a href="javascript: history.go(-1)">Back</a>
</body></html>
<?php
} else {
header('Location: http://muuttuja.org/tomenet/monsters/');
}
?>
parser.php
<?php
/* TomeNET r_info.txt parser by mikaelh */
/* Some settings */
if (!isset($server_settings)) $server_settings = array('RPG_SERVER', 'ENABLE_MAIA');
if (!isset($use_compression)) $use_compression = TRUE;
if (!isset($use_serialized)) $use_serialized = FALSE;
if (!isset($r_info_file)) {
$r_info_file = 'r_info.txt';
if ($use_compression) $r_info_file .= '.gz';
}
$found_serialized = FALSE;
if ($use_serialized) {
if (substr($r_info_file, -3) == '.gz') {
$serialized_file = basename($r_info_file, '.gz') . '.serialized.gz';
} else {
$serialized_file = $r_info_file . '.serialized';
}
if (file_exists($serialized_file)) {
$found_serialized = TRUE;
$r_info_file = $serialized_file;
}
}
if (file_exists($r_info_file)) {
$r_info_contents = "";
if ($use_compression) {
$fp = gzopen($r_info_file, 'rb');
if ($fp === FALSE) {
echo('ERROR in ' . __FILE__ . ' on line ' . __LINE__ . ': File ' . $r_info_file . "could not be opened\n");
die();
}
while (!gzeof($fp)) {
$r_info_contents .= gzread($fp, 8192);
}
gzclose($fp);
} else {
$fp = fopen($r_info_file, 'rb');
if ($fp === FALSE) {
echo('ERROR in ' . __FILE__ . ' on line ' . __LINE__ . ': File ' . $r_info_file . "could not be opened\n");
die();
}
while (!feof($fp)) {
$r_info_contents .= fread($fp, 8192);
}
fclose($fp);
}
} else {
echo('ERROR in ' . __FILE__ . ' on line ' . __LINE__ . ': File ' . $r_info_file . " doesn't exists!\n");
die();
}
$monster_types_enum = array(
'NONEBAND' => 0,
'BASEANGBAND' => 1,
'ZANGBAND' => 2,
'CTHANGBAND' => 3,
'JOKEANGBAND' => 4,
'PERNANGBAND' => 5,
'BLUEBAND' => 6,
);
$monster_types_bits = array(
'BASEANGBAND' => 0x01,
'ZANGBAND' => 0x02,
'CTHANGBAND' => 0x04,
'JOKEANGBAND' => 0x08,
'PERNANGBAND' => 0x10,
'BLUEBAND' => 0x20,
'NONEBAND' => 0x40,
);
function parse_r_info($r_info_contents, $server_settings) {
global $info_version;
$monster_types_enum = $GLOBALS['monster_types_enum'];
$monster_types_bits = $GLOBALS['monster_types_bits'];
$r_info = explode("\n", $r_info_contents);
$monsters = array();
$cur_monster = -1;
$cur_attack = 0;
// Defaults for monster entries
// Description is empty
// No body parts
// 20% chance for object drop rates
// Empty arrays for attacks, flags and spells
$monster_defaults = array(
'number' => 0,
'name' => NULL,
'symbol' => NULL,
'color' => NULL,
'speed' => 0,
'hp' => NULL,
'vision' => 0,
'ac' => 0,
'alertness' => 0,
'depth' => 0,
'rarity' => 0,
'weight' => 0,
'exp' => 0,
'treasure' => 20,
'combat' => 20,
'magic' => 20,
'tool' => 20,
'weapons' => 0,
'torso' => 0,
'arms' => 0,
'finger' => 0,
'head' => 0,
'leg' => 0,
'description' => '',
'attacks' => array(),
'flags' => array(),
'spells' => array(),
'spell_chance' => 0,
'type' => 0,
'type_bit' => $monster_types_bits['NONEBAND'],
'matches' => TRUE,
);
$monster = $monster_defaults;
foreach ($r_info as $row) {
$row = trim($row);
if (empty($row) || $row[0] == '#') {
continue;
}
while ($row[0] == '$') {
/* Process a server setting condition */
$next_dol = strpos($row, '$', 1);
$next_neg = strpos($row, '!', 1);
if (($next_neg === FALSE || $next_neg > $next_dol) && $next_dol !== FALSE) {
if ($next_dol === FALSE) {
echo('ERROR in ' . __FILE__ . ' on line ' . __LINE__ . ": Invalid server setting condition\n");
echo($row . "\n");
die();
}
$negation = FALSE;
$server_cond = substr($row, 1, $next_dol - 1);
$row = substr($row, $next_dol + 1);
} else {
$negation = TRUE;
$server_cond = substr($row, 1, $next_neg - 1);
$row = substr($row, $next_neg + 1);
}
if (!in_array($server_cond, $server_settings) ^ $negation) {
continue;
}
}
if ($row[1] == ':') {
$row_type = $row[0];
$row_data = explode(':', $row);
switch ($row_type) {
case 'V':
$info_version = substr($row, 2);
break;
case 'N':
// store previous monster
if ($cur_monster >= 0) {
$monsters[$cur_monster] = $monster;
}
$cur_monster = (int) $row_data[1];
$cur_attack = 0;
$monster = $monster_defaults;
$monster['number'] = (int) $row_data[1];
$monster['name'] = $row_data[2];
break;
case 'G':
$monster['symbol'] = $row_data[1];
$monster['color'] = $row_data[2];
break;
case 'I':
$monster['speed'] = (int) $row_data[1];
$monster['hp'] = $row_data[2];
$monster['vision'] = (int) $row_data[3];
$monster['ac'] = (int) $row_data[4];
$monster['alertness'] = (int) $row_data[5];
break;
case 'W':
$monster['depth'] = (int) $row_data[1];
$monster['rarity'] = (int) $row_data[2];
$monster['weight'] = (int) $row_data[3];
$monster['exp'] = (int) $row_data[4];
break;
case 'E':
$monster['weapons'] = (int) $row_data[1];
$monster['torso'] = (int) $row_data[2];
$monster['arms'] = (int) $row_data[3];
$monster['finger'] = (int) $row_data[4];
$monster['head'] = (int) $row_data[5];
$monster['leg'] = (int) $row_data[6];
break;
case 'O':
$monster['treasure'] = (int) $row_data[1];
$monster['combat'] = (int) $row_data[2];
$monster['magic'] = (int) $row_data[3];
$monster['tool'] = (int) $row_data[4];
break;
case 'B':
$monster['attacks'][$cur_attack++] = array('method' => $row_data[1], 'effect' => $row_data[2], 'damage' => isset($row_data[3]) ? $row_data[3] : NULL);
break;
case 'F':
$flags = explode('|', $row_data[1]);
foreach ($flags as $flag)
{
$flag = trim($flag);
if (empty($flag)) continue;
$monster['flags'][] = $flag;
if (isset($monster_types_enum[$flag])) {
$monster['type'] = $monster_types_enum[$flag];
$monster['type_bit'] = $monster_types_bits[$flag];
}
}
break;
case 'S':
$spells = explode('|', $row_data[1]);
foreach ($spells as $spell)
{
$spell = trim($spell);
if (empty($spell)) continue;
if (strpos($spell, '1_IN_') !== FALSE)
{
$monster['spell_chance'] = (int) substr($spell, 5);
continue;
}
$monster['spells'][] = $spell;
}
break;
case 'D':
if ($monster['description'] != '')
{
$monster['description'] .= "\n" . substr($row, 2);
} else {
$monster['description'] = substr($row, 2);
}
break;
default:
echo("WARNING: Unknown row type in r_info.txt: $row_type\n");
}
}
}
// store last monster
if ($cur_monster >= 0) {
$monsters[$cur_monster] = $monster;
}
// HACK - Replace NULL value for "Player"
$monsters[0]['hp'] = '1d1';
return $monsters;
}
if ($use_serialized && $found_serialized) {
$monsters = unserialize($r_info_contents);
} else {
$monsters = parse_r_info($r_info_contents, $server_settings);
}
/* Don't pollute the enviroment */
unset($r_info_contents);
?>
r_info_sort.php
<?php
$use_compression = FALSE;
require('parser.php');
function monster_level_sort($a, $b) {
if (array_key_exists('depth', $a) < array_key_exists('depth', $b)) {
return -1;
}
elseif (array_key_exists('depth', $a) > array_key_exists('depth', $b)) {
return 1;
}
elseif ($a['depth'] < $b['depth']) {
return -1;
}
elseif ($a['depth'] > $b['depth']) {
return 1;
}
elseif ($a['number'] < $b['number']) {
return -1;
}
elseif ($a['number'] > $b['number']) {
return 1;
}
else {
return 0;
}
}
usort($monsters, 'monster_level_sort');
$fp = fopen('r_info_sorted.txt', 'w');
fwrite($fp, 'V:' . $info_version . "\n");
foreach ($monsters as $m) {
fwrite($fp, 'N:' . $m['number'] . ':' . $m['name'] . "\n");
fwrite($fp, 'G:' . $m['symbol'] . ':' . $m['color'] . "\n");
if (isset($m['speed'])) fwrite($fp, 'I:' . $m['speed'] . ':' . $m['hp'] . ':' . $m['vision'] . ':' . $m['ac'] . ':' . $m['alertness'] . "\n");
fwrite($fp, 'W:' . $m['depth'] . ':' . $m['rarity'] . ':' . $m['weight'] . ':' . $m['exp'] . "\n");
if (isset($m['weapons'])) fwrite($fp, 'E:' . $m['weapons'] . ':' . $m['torso'] . ':' . $m['arms'] . ':' . $m['finger'] . ':' . $m['head'] . ':' . $m['leg'] . "\n");
if (isset($m['treasure'])) fwrite($fp, 'O:' . $m['treasure'] . ':' . $m['combat'] . ':' . $m['magic'] . ':' . $m['tool'] . "\n");
foreach ($m['attacks'] as $a) {
if (!empty($a['damage'])) {
fwrite($fp, trim('B:' . $a['method'] . ':' . $a['effect'] . ':' . $a['damage']) . "\n");
} else {
fwrite($fp, trim('B:' . $a['method'] . ':' . $a['effect']) . "\n");
}
}
if (count($m['flags']) > 0) fwrite($fp, 'F:' . implode('|', $m['flags']) . "\n");
if (!empty($m['spell_chance'])) fwrite($fp, 'S:1_IN_' . $m['spell_chance'] . "\n");
if (count($m['spells']) > 0) fwrite($fp, 'S:' . implode('|', $m['spells']) . "\n");
if (!empty($m['description'])) {
foreach (explode("\n", $m['description']) as $d) {
fwrite($fp, 'D:' . $d . "\n");
}
}
}
?>
spells.php
<?php
$spells = array('ARROW_1', 'ARROW_2', 'ARROW_3', 'ARROW_4', 'BA_ACID', 'BA_CHAO', 'BA_COLD', 'BA_DARK', 'BA_ELEC', 'BA_FIRE', 'BA_MANA', 'BA_NETH', 'BA_NUKE', 'BA_POIS', 'BA_WATE', 'BLIND', 'BLINK', 'BOULDER', 'BO_ACID', 'BO_COLD', 'BO_DISE', 'BO_ELEC', 'BO_FIRE', 'BO_ICEE', 'BO_MANA', 'BO_NETH', 'BO_PLAS', 'BO_POIS', 'BO_WATE', 'BRAIN_SMASH', 'BR_ACID', 'BR_CHAO', 'BR_COLD', 'BR_CONF', 'BR_DARK', 'BR_DISE', 'BR_DISI', 'BR_ELEC', 'BR_FIRE', 'BR_GRAV', 'BR_INER', 'BR_LITE', 'BR_MANA', 'BR_NETH', 'BR_NEXU', 'BR_NUKE', 'BR_PLAS', 'BR_POIS', 'BR_SHAR', 'BR_SOUN', 'BR_TIME', 'BR_WALL', 'CONF', 'CURSE', 'DARKNESS', 'DRAIN_MANA', 'FORGET', 'HASTE', 'HEAL', 'HOLD', 'MIND_BLAST', 'MISSILE', 'MOAN', 'RAISE_DEAD', 'ROCKET', 'SCARE', 'SHRIEK', 'SLOW', 'S_ANGEL', 'S_ANIMAL', 'S_ANIMALS', 'S_ANT', 'S_BUG', 'S_DEMON', 'S_DRAGON', 'S_DRAGONRIDER', 'S_HI_DEMON', 'S_HI_DRAGON', 'S_HI_MONSTERS', 'S_HI_UNDEAD', 'S_HI_UNIQUE', 'S_HOUND', 'S_HYDRA', 'S_KIN', 'S_MONSTER', 'S_MONSTERS', 'S_NAZGUL', 'S_RNG', 'S_SPIDER', 'S_UNDEAD', 'S_UNIQUE', 'TELE_AWAY', 'TELE_LEVEL', 'TELE_TO', 'TPORT', 'TRAPS', 'UNMAGIC');
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><title>List of spells | TomeNET monster search</title></head><body bgcolor=#ffffff><h1>List of spells used in r_info.txt</h1><table border=0 cellpadding=0 cellspacing=1 width=100%><tr>
<?php
for ($i = 0, $n = count($spells); $i < $n; $i++)
{
echo('<td>' . $spells[$i] . '</td>');
if (($i + 1) % 3 == 0)
{
echo ('</tr><tr>');
}
}
?>
</tr></table>
<p><a href="javascript: history.go(-1)">Back</a></p>
</body></html>