The RPG Maker Resource Kit

RMRK RPG Maker Creation => RPG Maker General => General Scripting => Topic started by: cozziekuns on August 03, 2011, 05:40:19 AM

Title: Movement Range Logic Help
Post by: cozziekuns on August 03, 2011, 05:40:19 AM
Can you spot the logic error in this? I sure can't :'(

(Ignore the terrible code; this stuff is like pre-alpha alpha).


def create_movement_range
   
    x = cursor_event[0].x
    y = cursor_event[0].y
    movement = cursor_event[0].battler[3]
   
    open = []
    closed = []
    parent_x = Table.new($game_map.width, $game_map.height)
    parent_y = Table.new($game_map.width, $game_map.height)
   
    for i in 0...$game_map.width
      for j in 0...$game_map.height
        parent_x[i, j] = -1
        parent_y[i, j] = -1
      end
    end
   
    open.push([x, y])
    closed = open.clone
    open.delete([x, y])
    open.push([x, y + 1]) if $game_map.passable?(x, y + 1)
    open.push([x, y - 1]) if $game_map.passable?(x, y - 1)
    open.push([x + 1, y]) if $game_map.passable?(x + 1, y)
    open.push([x - 1, y]) if $game_map.passable?(x - 1, y)
   
    for point in open
      parent_x[point[0], point[1]] = x
      parent_y[point[0], point[1]] = y
    end
   
    loop do
     
      lowest = 9999
     
      for point in open
       
        dist = ((point[0] - x).abs + (point[1] - y).abs) * 10
        next if dist > lowest
        iterations = 0
        point_x = point[0]
        point_y = point[1]
       
        loop do
         
          if not (point_x - parent_x[point_x, point_y]) == 0
            if not parent_x[point_x, point_y] == -1
              point_x -= (point_x - parent_x[point_x, point_y])
              iterations += 1
            end
          elsif not (point_y - parent_y[point_x, point_y]) == 0
            if not parent_y[point_x, point_y] == -1
              point_y -= (point_y - parent_y[point_x, point_y])
              iterations += 1
            end
          else
            break
          end
         
          break if parent_x[point_x, point_y] == -1 and parent_y[point_x, point_y] == -1
         
        end       
       
        lowest = dist
        lowest_point = point
       
      end
     
      break if iterations > movement
       
      open.delete(lowest_point)
      closed.push(lowest_point)
     
      ax = lowest_point[0]
      ay = lowest_point[1]
     
      for i in 0..3
        case i
        when 0; key = [ax, ay + 1]
        when 1; key = [ax, ay - 1]
        when 2; key = [ax + 1, ay]
        when 3; key = [ax - 1, ay]
        end
        next unless $game_map.passable?(key[0], key[1])
        next if closed.include?(key)
        open.push(key)
       
        parent_x[key[0], key[1]] = lowest_point[0]
        parent_y[key[0], key[1]] = lowest_point[1]
      end
     
    end
   
    @points = closed

  end


Background: I was playing around with a turn based tactics like movement system, where your movement is limited by steps (iterations in this algorithm). I was attempting to use Dijkstra's pathfinding algorithm by spliltting the map into the standard 32 * 32 grid, and checking the amount of iterations to create my movement range. I can't see what's wrong with this, but RPG Maker begs to differ:

(https://rmrk.net/proxy.php?request=http%3A%2F%2Fi56.tinypic.com%2Fwup7uo.png&hash=c6aadf14293594e8a6737d10991d7afe4585e3f3)

(Movement Range is 4)

(https://rmrk.net/proxy.php?request=http%3A%2F%2Fi51.tinypic.com%2Feg6bg3.png&hash=ae0a1cf872d62f716019c3a9072a25436b2ad5cd)

(Movement Range is 3) This works fine.

Demo attached if you don't want to work blind. Thanks for your help, guys.
Title: Re: Movement Range Logic Help
Post by: cozziekuns on August 03, 2011, 04:19:03 PM
Pardon the double post but I took out the heuristic (not sure why it was there in the first place), and it seems to be working fine now.


def create_movement_range
   
    x = cursor_event[0].x
    y = cursor_event[0].y
    movement = cursor_event[0].battler[3]
   
    open = []
    closed = []
    parent_x = Table.new($game_map.width, $game_map.height)
    parent_y = Table.new($game_map.width, $game_map.height)
   
    for i in 0...$game_map.width
      for j in 0...$game_map.height
        parent_x[i, j] = -1
        parent_y[i, j] = -1
      end
    end
   
    open.push([x, y])
    closed = open.clone
    open.delete([x, y])
    open.push([x, y + 1]) if $game_map.passable?(x, y + 1)
    open.push([x, y - 1]) if $game_map.passable?(x, y - 1)
    open.push([x + 1, y]) if $game_map.passable?(x + 1, y)
    open.push([x - 1, y]) if $game_map.passable?(x - 1, y)
   
    for point in open
      parent_x[point[0], point[1]] = x
      parent_y[point[0], point[1]] = y
    end
   
    loop do
     
      lowest = 9999
     
      for point in open
       
        iterations = 0
        point_x = point[0]
        point_y = point[1]
       
        loop do
         
          if not (point_x - parent_x[point_x, point_y]) == 0
            if not parent_x[point_x, point_y] == -1
              point_x -= (point_x - parent_x[point_x, point_y])
              iterations += 1
            end
          elsif not (point_y - parent_y[point_x, point_y]) == 0
            if not parent_y[point_x, point_y] == -1
              point_y -= (point_y - parent_y[point_x, point_y])
              iterations += 1
            end
          else
            break
          end
         
          break if parent_x[point_x, point_y] == -1 and parent_y[point_x, point_y] == -1
         
        end 
       
        next if iterations > lowest
       
        lowest = iterations
        lowest_point = point
       
      end
     
      break if lowest > movement
       
      open.delete(lowest_point)
      closed.push(lowest_point)
     
      ax = lowest_point[0]
      ay = lowest_point[1]
     
      for i in 0..3
        case i
        when 0; key = [ax, ay + 1]
        when 1; key = [ax, ay - 1]
        when 2; key = [ax + 1, ay]
        when 3; key = [ax - 1, ay]
        end
        next unless $game_map.passable?(key[0], key[1])
        next if closed.include?(key)
        open.push(key)
       
        parent_x[key[0], key[1]] = lowest_point[0]
        parent_y[key[0], key[1]] = lowest_point[1]
      end
     
    end
   
    @points = closed
   
  end


Gonna leave this open just in case anyone comes up with a better algorithm.
Title: Re: Movement Range Logic Help
Post by: dricc on August 04, 2011, 12:32:43 PM
Wait ... you're working on a TBS ???
2 TBS are already existing but you probably know it . both aren't perfect and can be improved .
What are the differences with your project ?
Title: Re: Movement Range Logic Help
Post by: pacdiggity on August 04, 2011, 12:42:54 PM
I'd say the most obvious difference is that he's making this one.
Title: Re: Movement Range Logic Help
Post by: dricc on August 04, 2011, 12:56:13 PM
yep , of course :)
But what i mean is that a lot of makers are complaining about the GTBS . it's a monster script with a lot of setup (and quite mysterious for some of them) and yes , some bugs .
So making another TBS as a sense ... especially if it's a most simple one .