Re: Webster van Robot help



On Dec 25, 5:00 pm, David Mark <dmark.cins...@xxxxxxxxx> wrote:
On Dec 25, 7:04 pm, Steve Howell <showel...@xxxxxxxxx> wrote:


Install Microsoft Script Debugger or Visual studio.


First, thanks for all your suggestions.

I will try the tools above soon, but right now I'm borrowing somebody
else's computer, so I'm reluctant to install software.

Are there any tricks for debugging IE as it comes shipped? I am
getting cryptic errors like this:

Line: 19
Char: 1
Error: Object expected

Is the line number relative to the <script> statement?



background-color:#EEEEEE; color:inherit


Done, although I don't understand what I'm fixing here.


Tiny is relative. Pixels are not.

font-size: 80%


Fixed.

function showMsg(the_message) {
document.the_form.the_text.value += (the_message + "\n");

document.forms['the_form'].elements['the_test'].value += ...


Done.


function World() {
this.robot_x = 1;
this.robot_y = 1;
this.robot_dir = "E";
this.north_walls = [];
this.east_walls = [];
this.num_aves = 12
this.num_streets = 10

I would think some of these should be parameters.


Eventually. As you notice in your later comments, the World() class
for now is just a singleton. The only reason I make it a class for
now is simple encapsulation. I want some of the implementation
details of the World model hidden from the rest of my code.

function _coords() {
return this.robot_x + "," + this.robot_y;
}
this._coords = _coords;

Why the leading underscore? What is that supposed to denote?


I was just using a naming convention to suggest that _coords was an
internal implementation detail, and that callers would not want to
call it. It turns out it was dead code anyway, so I removed it.


Your semi-colon key seems to have broke at this point.


I've obviously been spoiled by Python, Ruby, Firefox JS, etc. I have
tried to sprinkle in semicolons to fix IE, but IE is still broken.


Use a switch statement.


Thanks, good suggestion. I have since used a switch statement in a
couple places, as well as associative arrays.

Why are all of the methods nested in the constructor? If you are
going to instantiate more than one of these (and if not, it doesn't
need to be a constructor), it will be more efficient to define the
methods as properties of the World prototype.


Efficiency is not a major goal for now. All I want is simple
encapsulation. I'm still getting my head around JS's object model.


function redraw_street(street)
{
/* showMsg('redraw' + street) */
row = document.getElementById("street"+street)

/* row = document.getElementById("street"+street) */
var text = '<th class="st east">S' + street + '</th>'
for (var ave = 1; ave <= the_world.num_aves; ++ave) {
text += the_world.render(ave, street)
}
row.innerHTML = text;

Here is where you are going to have trouble with IE. Your best bet is
to rewrite the bits that use innerHTML (use DOM methods instead.)


I would prefer to use the DOM, but when I tried that at first, I was
running into issues. I may have been fighting some red herrings due
to CSS, though, so I will try soon to go back to a more DOM-oriented
style.


<a href="#" onClick="move(); return false;">move</a>
<a href="#" onClick="turnleft(); return false;">turnleft</a>
<a href="#" onClick="turnright(); return false;">turnright</a>
<a href="#" onClick="build_wall_on_left(); return
false;">build_wall_on_left</a>
<a href="#" onClick="start_over(); return false;">start_over</a>

These links (should really be buttons) should be generated with
script. They aren't going to do anything useful without script.


I'm not sure what you mean by that. The links work exactly as I
expect. When I click move, the robot does in fact move.

Here's the latest version:

<html>

<style type="text/css">
table {border-collapse: collapse;}
table.wvr th {background-color: #EEEEEE; color: inherit;}
table.wvr td {background: #FFFF00}
table.wvr td, th {height: 40px; width: 40px; text-align: center}
..heading {background: #FF00FF}
..north {border-top: solid red;}
..east {border-right: solid red;}
..no_north {border-top: solid white;}
..no_east {border-right: solid white;}
..robot {background: #FF8888}
..beeper {background: #00FFFF}
..tiny {font-size: 70%}
</style>


<body onload="create_world()">
<script type="text/javascript">
/*
Webster van Robot.
(c) GNU General Public license
*/

function text_box() {
return document.forms['the_form'].elements['the_text'];
}

function showMsg(the_message) {
text_box().value += the_message + "\n";
}

function clearMsg() {
text_box().value = '';
}

function World() {
this.robot_x = 1;
this.robot_y = 1;
this.robot_dir = "E";
this.north_walls = [];
this.east_walls = [];
this.num_aves = 12;
this.num_streets = 10;
this.left = {
'N': 'W',
'W': 'S',
'S': 'E',
'E': 'N'};
this.right = {
'N': 'E',
'E': 'S',
'S': 'W',
'W': 'N'};
this.robot_char = {
'N': '^',
'E': '>',
'S': 'v',
'W': '<',
}

function wall_on_north(x, y)
{
if (y == 0 || y == this.num_streets) {
return true;
}
coords = x + "," + y;
return (this.north_walls[coords] == 1);
}
this.wall_on_north = wall_on_north;

function wall_on_south(x, y)
{
return this.wall_on_north(x, y - 1);
}
this.wall_on_south = wall_on_south;

function wall_on_east(x, y)
{
if (x == 0 || x == this.num_aves) {
return true;
}
coords = x + "," + y;
return (this.east_walls[coords] == 1);
}
this.wall_on_east = wall_on_east;

function wall_on_west(x, y)
{
return this.wall_on_east(x - 1, y);
}
this.wall_on_west = wall_on_west;

function is_facing_wall() {
switch (this.robot_dir) {
case 'N':
return this.wall_on_north(this.robot_x, this.robot_y);
case 'W':
return this.wall_on_west(this.robot_x, this.robot_y);
case 'S':
return this.wall_on_south(this.robot_x, this.robot_y);
case 'E':
return this.wall_on_east(this.robot_x, this.robot_y);
}
}
this.is_facing_wall = is_facing_wall;

function move() {
if (this.is_facing_wall()) {
return 'blocked by wall';
}
switch (this.robot_dir) {
case 'N': this.robot_y += 1; break;
case 'W': this.robot_x -= 1; break;
case 'S': this.robot_y -= 1; break;
case 'E': this.robot_x += 1; break;
}
}
this.move = move;

function turnleft() {
this.robot_dir = this.left[this.robot_dir];
}
this.turnleft = turnleft;

function turnright() {
this.robot_dir = this.right[this.robot_dir];
}
this.turnright = turnright;

function build_east_wall(x, y) {
if (this.wall_on_east(x, y)) {
return 'There is already a wall there';
}
coords = x + "," + y;
this.east_walls[coords] = 1;
}
this.build_east_wall = build_east_wall;

function build_west_wall(x, y) {
return this.build_east_wall(x-1, y);
}
this.build_west_wall = build_west_wall;

function build_north_wall(x, y) {
if (this.wall_on_north(x, y)) {
return 'There is already a wall there';
}
coords = x + "," + y;
this.north_walls[coords] = 1;
}
this.build_north_wall = build_north_wall;

function build_south_wall(x, y) {
return this.build_north_wall(x, y-1);
}
this.build_south_wall = build_south_wall;

function build_wall_on_left() {
x = this.robot_x;
y = this.robot_y;
switch (this.robot_dir) {
case 'N': return this.build_west_wall(x, y);
case 'S': return this.build_east_wall(x, y);
case 'E': return this.build_north_wall(x, y);
case 'W': return this.build_south_wall(x, y);
}
}
this.build_wall_on_left = build_wall_on_left;

function robot() {
return this.robot_char[this.robot_dir];
}
this.robot = robot;

function render(avenue, street)
{
var data = '';
var klass = '';
var coords = avenue + ',' + street;

if (this.north_walls[coords] == 1) {
klass += 'north';
}
else {
klass += 'no_north';
}

if (this.east_walls[coords] == 1) {
klass += ' east';
}
else {
klass += ' no_east';
}

if (this.robot_x == avenue && this.robot_y == street) {
data = '<div class="robot">' + this.robot() + '</div>';
}
else {
data = '<div class="tiny">' + coords + '</div>';
}

var text = '<td class="' + klass + '">' + data + '</td>';
return text;
}
this.render = render;
}

the_world = new World();

function start_over() {
the_world = new World();
redraw_grid();
clearMsg();
}

function redraw_street(street)
{
row = document.getElementById("street"+street);

var text = '<th class="st east">S' + street + '</th>';
for (var ave = 1; ave <= the_world.num_aves; ++ave) {
text += the_world.render(ave, street);
}
row.innerHTML = text;
row.id = 'street' + street;
}

function create_world() {
ave_row = document.getElementById("ave_heading");
text = '<th></th>';
for (var ave = 1; ave <= the_world.num_aves; ++ave) {
text += '<th class="ave">A' + ave + '</td>';
}
ave_row.innerHTML = text;

table = document.getElementById("world");
for (var street = 1; street <= the_world.num_streets; ++street) {
x = table.insertRow(2);
x.id = "street"+street;
}
redraw_grid();
}

function redraw_grid() {
for (var street = 1; street <= the_world.num_streets; ++street) {
redraw_street(street);
}
}

function redraw_to_bottom(street) {
for (var i = street; i >= 1; --i) {
redraw_street(i);
}
}

function move() {
old_street = the_world.robot_y;
problem = the_world.move();
if (problem) {
alert(problem);
return problem;
}
showMsg('move');
new_street = the_world.robot_y;
redraw_street(old_street);
redraw_street(new_street);
}

function turnleft() {
showMsg('turnleft');
the_world.turnleft();
street = the_world.robot_y;
redraw_street(street);
}

function turnright() {
showMsg('turnright');
the_world.turnright();
street = the_world.robot_y;
redraw_street(street);
}


function build_wall_on_left() {
problem = the_world.build_wall_on_left()
if (problem) {
alert(problem);
return problem;
}
showMsg('build_wall_on_left');
var street = the_world.robot_y;
redraw_to_bottom(street); /* browsers are stupid */
}
</script>

<table>
<tr>
<td valign="top">
<a href="#" onClick="move(); return false;">move</a>
<a href="#" onClick="turnleft(); return false;">turnleft</a>
<a href="#" onClick="turnright(); return false;">turnright</a>
<a href="#" onClick="build_wall_on_left(); return
false;">build_wall_on_left</a>
<a href="#" onClick="start_over(); return false;">start_over</a>



<table id="world" class="wvr">
<tr>
<th colspan=13 class="heading">Webster van Robot's World</th>
</tr>
<tr id="ave_heading">
</tr>
<tr class="north"></tr>
</table>


</td>
<td>

<form name="the_form">
<textarea name="the_text" rows=30 cols=40>
</textarea>
</form>

</td>
</tr>
</table>

</body>
</html>
.