        public static function eval_1x1(i:int, j:int):Number { /* {{{ */
            for (var ii:int=-1; ii <= 1; ++ii) {
                for (var jj:int=-1; jj <= 1; ++jj) {
                    if (i+ii > 0 && i + ii < 21) {
                        if (j+jj > 0 && j + jj < 21) {
                            eval_cache_map[i+ii][j+jj] = map[i+ii][j+jj];
                        }
                    }
                }
            }
            return eval_cache[i][j] = (
                        (wood_weight != 0.0 ? get_resource_value(WOOD, i, j) * wood_weight : 0.0)+
                        (stone_weight != 0.0 ? get_resource_value(STONE, i, j) * stone_weight : 0.0)+
                        (iron_weight != 0.0 ? get_resource_value(IRON, i, j) * iron_weight : 0.0)+
                        (food_weight != 0.0 ? get_resource_value(FOOD, i, j) * food_weight : 0.0)+
                        (gold_weight != 0.0 ? get_gold_value(i, j) * gold_weight : 0.0));
        } /* }}} */
        public static function reset_eval_cache():void { /* {{{ */
            eval_cache_wood_weight = wood_weight;
            eval_cache_stone_weight = stone_weight;
            eval_cache_iron_weight = iron_weight;
            eval_cache_food_weight = food_weight;
            eval_cache_gold_weight = gold_weight;

            for (var i:int=0; i < 21; ++i) {
                for (var j:int=0; j < 21; ++j) {
                    eval_cache[i][j] = 0;
                    eval_cache_map[i][j] = WALL;
                }
            }
        } /* }}} */
        public static function eval_3x3(i:int, j:int):Number { /* {{{ */
            if (eval_cache_wood_weight != wood_weight 
                || eval_cache_stone_weight != stone_weight 
                || eval_cache_iron_weight != iron_weight 
                || eval_cache_food_weight != food_weight 
                || eval_cache_gold_weight != gold_weight) 
            {
                reset_eval_cache();
            }

            var need_to_recompute:Boolean = false;
            for (var ii:int=-2; ii <= 2; ++ii) {
                for (var jj:int=-2; jj <= 2; ++jj) {
                    if (ii+i > 0 && ii+i < 21) {
                        if (jj+j > 0 && jj+j < 21) {
                            if (map[i+ii][j+jj] != eval_cache_map[i+ii][j+jj]) { 
                                need_to_recompute = true;
                                break;
                            }
                        }
                    }
                }
            }

            /* we don't get too fancy here... if anything changed in our vicinity, we 
             * just recompute the grid. We could probably futher figure out which spots
             * needed recomputation, but i'm a bit lazy for that right now. */
            if (need_to_recompute) {
                eval_1x1(i-1,j-1);
                eval_1x1(i-1,j  );
                eval_1x1(i-1,j+1);

                eval_1x1(i  ,j-1);
                eval_1x1(i  ,j  );
                eval_1x1(i  ,j+1);

                eval_1x1(i+1,j-1);
                eval_1x1(i+1,j  );
                eval_1x1(i+1,j+1);
            }

            return eval_cache[i-1][j-1]
                 + eval_cache[i-1][j  ]
                 + eval_cache[i-1][j+1]

                 + eval_cache[i  ][j-1]
                 + eval_cache[i  ][j  ]
                 + eval_cache[i  ][j+1]

                 + eval_cache[i+1][j-1]
                 + eval_cache[i+1][j  ]
                 + eval_cache[i+1][j+1];
        } /* }}} */
