Pathfinding in PHP

I’ve been playing around with doing some A* pathfinding scripts.  I was looking around on the web and didn’t find any anywhere, so I decided to make my own rudimentary one.  I’m going to be expounding on this later.  I thought about looking into the A* method and a few others.  Feel free to take the sample below.  Here is a demo too.

<style>
 * {
 margin: 0px;
 padding: 0px;
 }
</style>
<body style="margin: 13px 0px 0px 0px; background: #000;">
<?php
 /* Set the size of our target area */
 $range = 3;

 /* Build the pathfinding function */
 function pathfind($current_square_x, $current_square_y, $map, $steps, $target) {
 /* Give the function a step limit.  We don't want to create an endless loop. */
 $max_steps = 100;

 /* Define the next steps */
 $next_steps[$current_square_y + 1]    [$current_square_x + 1]    = "";
 $next_steps[$current_square_y + 1]    [$current_square_x]     = "";
 $next_steps[$current_square_y + 1]    [$current_square_x - 1]    = "";
 $next_steps[$current_square_y - 1]    [$current_square_x + 1]    = "";
 $next_steps[$current_square_y - 1]    [$current_square_x]        = "";
 $next_steps[$current_square_y - 1]    [$current_square_x - 1]    = "";
 $next_steps[$current_square_y]        [$current_square_x + 1]    = "";
 $next_steps[$current_square_y]        [$current_square_x - 1]    = "";

 /* Do some math to find the distance from here (as the crow flies) to the target) */
 $height = sizeof($map);
 $width = sizeof($map[0]);
 $minimum = sqrt(($width * $width) + ($height * $height));

 /* Find the closest tile */
 foreach($next_steps as $y_key => $y_value) {
 foreach($y_value as $x_key => $x_value) {
 if(
 isset($map[$y_key][$x_key]) &&
 $map[$y_key][$x_key] != "closed" &&
 $map[$y_key][$x_key] != "start" &&
 $steps < $max_steps
 ) {
 if($map[$y_key][$x_key] != "traversed") {
 $width  = abs($x_key - $target['x']) + 1;
 $height = abs($y_key - $target['y']) + 1;
 $c = round(sqrt(($width * $width) + ($height * $height)),2);

 if($c < $minimum) {
 $minimum = $c;
 $lowest_distance_position = $x_key."x".$y_key;
 }
 }
 }
 }
 }

 /* Start the next calculation from the closest tile */
 $position = explode("x",$lowest_distance_position);

 if(
 isset($map[$position[1]][$position[0]]) &&
 !($position[0] == $target['x'] && $position[1] == $target['y'])
 ) {
 $map[$position[1]][$position[0]] = "traversed";

 $path[$position[0]."x".$position[1]] =
 pathfind($position[0], $position[1], $map, $steps + 1, $target);

 if($path) {
 return $path;
 break;
 }
 }

 return array($position[0]."x".$position[1] => "target");
 break;
 }

 /* Convert the three based array to a step based array. */
 function build_path($path_array, $step_number) {
 if(sizeof($path_array) > 0 && is_array($path_array)) {
 foreach($path_array as $key => $value) {
 $this_path[$step_number] = $key;

 if(sizeof($path_array[$key]) > 0) {
 $built_path =
 array_merge(
 $this_path,
 build_path($path_array[$key], $step_number++)
 );
 return $built_path;
 }
 }
 } else {
 return array();
 }
 }

 /* Set the map size. */
 $map_size_x = 43;
 $map_size_y = 22;

 /* Build the blank map. */
 for($y = 0; $y < $map_size_y; $y++) {
 for($x = 0; $x < $map_size_x; $x++) {
 $map[$y][$x] = "open";
 }
 }

 /* Set special sections of the map. */
 $map[15][25] = "closed";
 $map[16][25] = "closed";
 $map[17][25] = "closed";
 $map[18][25] = "closed";
 $map[19][25] = "closed";
 $map[20][25] = "closed";
 $target['x'] = 39;
 $target['y'] = 18;
 $start['x'] = 1;
 $start['y'] = 1;

 $path = pathfind($start['x'], $start['y'], $map, 0, $target);
 $built_path = build_path($path, 1);

 /* Output the final map. */
 echo "<table style="margin: 0px auto;">";

 foreach($map as $y_key => $y_value) {
 echo "<tr>";

 foreach($y_value as $x_key => $x_value) {
 if($x_value == "closed") {
 $background = "F99";
 } elseif ($x_value == "path") {
 $background = "9F9";
 } elseif ($x_key == $start['x'] && $y_key == $start['y']) {
 $background = "559";
 } elseif (
 $x_key < $target['x'] + $range &&
 $x_key > $target['x'] - $range &&
 $y_key < $target['y'] + $range &&
 $y_key > $target['y'] - $range
 ) {
 $background = "900";
 } elseif(in_array($x_key."x".$y_key,$built_path)) {
 $background = "353";
 } else {
 $background = "333";
 }

 echo
 "<td
 style="
 background: #".$background.";
 width: 20px;
 height: 20px;
 text-align: center;
 ">
 </td>";
 }

 echo "</tr>";
 }

 echo "</table>";
?>
<pre>
 <?php
 //print_r($path);
 ?>
</pre>
</body>

Project: Toolerific.com

I just threw this website together for my own use like a year ago.  Right now there are the three most common tools I use.  I couldn’t really think of anything else that I would have used, but the three tools are:

  • Creating MD5 Hashes,
  • Whois Lookups, and
  • Public IP Address Checking

I use it all the time, so I thought I’d tell you about it.

Using Javascript for Commenting in Inputs

You can use Javascript to build inline comments for your input fields.  This is a great way to denote required fields and pre-populate data.  If you’re using this script to show comments on required fields, I would suggest combining it with some sort of server or client side validation script – or both.  The code is an example SIMILAR to the way WordPress’s comments form looks.  Some day I will build a widget for this.

The Code

<h4>Leave a Reply</h4>
<form action="action.php" method="post" id="commentform">
  <div class="inputs">
    <input type="text" name="author" id="author"
      onClick="removeTextCheck(this,'(Required)');"
      onBlur="addTextCheck(this,'(Required)');"
      value="(Required)" />
    <input type="text" name="email" id="email"
      onClick="removeTextCheck(this,'(Required)');"
      onBlur="addTextCheck(this,'(Required)');"
      value="(Required)" />
    <input type="text" name="url" id="url" value="" />
  </div>
  <textarea name="comment" id="comment"
    onClick="removeTextCheck(this,'(Your Message)');"
    onBlur="addTextCheck(this,'(Your Message)');">(Your Message)</textarea>
</form>
<script type="text/javascript">
  function removeTextCheck(element,initialValue) {
    if(element.value == initialValue) element.value = "";
  }

  function addTextCheck(element,initialValue) {
    if(element.value == "") element.value = initialValue;
  }
</script>

Explanation

This code is actually pretty simple.  For each element that you wish to do an inline comment for, you’ll need an “onClick” even and an “onBlur” event.  For the “onClick” event you’ll create a function called “removeTextCheck” and call it in each input or text area that you’d like to leave an inline comment for.  For the “onBlur” event, you’ll create a function called “addTextCheck” and call it in each input or text area that you’d like to leave an inline comment for.

Both functions have two arguments: “element” and “initialValue” which have pretty much the same definition in both functions.  The “element” argument is the element in which you are placing the inline comment.  You will always use the “this” variable when calling this function inline.  If you call it from somewhere else in your page you may want to use something like “getElementById” or something similar.  The second argument “initialValue” will be the value that you wish to check against for adding/removing the text.  In my code above, that was either the “(Required)” values or the “(Your Message)” value.  You will want to make sure that this argument matches the value attribute of either your input or textarea.

Did this make sense to you?  Let me know!

Oh, and the code above can be copied and pasted as is into a blank text document to creat a working page.

Saving Bandwidth with Google Ajax Libraries API

The News

I first heard about the new Google AJAX Libraries API from Jeremy Schoemaker’s blog.  He mentions using it to reduce WordPress bandwidth, but really it can be used to reduce bandwidth in most AJAX based web development environments.

The Exciting Part

I persoanlly use prototype the most, and I’m extremely excited that I can use their libraries instead of uploading my own for each site.  I’m especially excited that calling specific version numbers is possible.  This makes upgrading a code set extremely simple, especially if you call the code version as a variable at the beginning of your code.

Realistically your javascript code is probably one of the lightest weight parts of your code, but every little bit helps, especially if you’re serving a large amount of users every month.

Optional Settings

Script Compression

I think one of the greatest optional settings for all of the scripts you can load is compression.  It’s not available for all of the APIs, but it is for most.  What it does is remove all of the whitespace from the API to reduce file size for the end user – increasing speed.  If you mix that with something like the javascript compiling on Google Chrome and you’ll have lightning fast AJAX applications.

No CSS

You can optionally remove the CSS from the scripts you’re remotly loading, which allows you to do one of three things: load the default CSS, load your own CSS, or not load the CSS at all.

Resources

WordPress.org: Google AJAX Libraries API Plugin – This plugin uses the GALA whereever possible in your WordPress installation.

Google AJAX APIs Blog – This is a great place to go if this really iterests you and you’ll be using this code regularly.  They’re always adding new scripts to the API, so if you don’t see the one you want yet, keep an eye on their blog.