Main Menu
  • Welcome to The RPG Maker Resource Kit.

Calculate Movable Spaces Trouble

Started by da good king, May 02, 2009, 08:07:01 AM

0 Members and 1 Guest are viewing this topic.

da good king

 I apologize in advance if this was supposed to be placed in the Scripts Support area, but I'm pretty sure help needed with others scripts goes here :P

I have been working on a Tactical Turn-Based game. Unfortunately, I want to make it in VX, (I like RGSS2 alot better :),) and so far there are no TBSs out since GTBS, which is not compatible with VX. Not only this, but there are numerous kinks with GTBD I want to get out, and many components I don't need (isometric, etc) that just get in the way of what I want. I'm therefore attempting to just do my own coding entirely, which has so far been perfectly fine, seeing as I've avoided the most basic and daunting thing: the game system. :( (I've been messing around with custom inventory systems and the like)

The biggest problem I am having is the very first thing to be done: moving... I first tried to find out logically the method behing moving, obstacles, terrain that "slows you down", etc (think: Fire Emblem) but I was at a loss for anything simple. So, I searched my folders and pulled out an old DL of Gubid's TBS, and took a look at what he did. I actually yelled out loud when I saw the 800 line method, calc_pos, the method for determining movable spaces. I took a long study of it, and after cropping out all the isometric and "ENCOUNTER MOVE METHOD" optional code found it the be only 400 lines. ;)
Nonetheless, this script is still proving disastrously hard to integrate into a fellow RMXP project, let alone VX. The even sadder part is, I haven't even addressed AI -_-...

So, I have two questions:
1) Should I just leave this and wait until someone makes a TBS? (I'm still a bit new to scripting anything beyond simple -_-, but it would make me sad to abandon this :()

2) Can someone take a look at this calc_pos method and try to make a friendlier version of it that I can integrate into VX or at least a new RMXP project? Even just explaining how this monster method works would be fine. (Just leave a comment for any variables I need to account for, such as base_move or an actor's x and y coords)
Also, for check_th, I haven't a clue what's going on there -_-.

Original GTBS

This is the watered down version of def calc_pos without the needless iso and ENCOUNTER METHOD branches
[spoiler="Calculate Positions Method"]  #----------------------------------------------------------
  #Calc_Pos - calculates tiles to be highlighted for spells, move, attack
  #----------------------------------------------------------
  def calc_pos(actor, range_max = 0, range_min = 0, type = "all", override = false)
    positions = []
    unless range_max == nil
      if range_max > -1 and type == "all"
        if @move_positions.size > 1 and override == false
          range_max -= actor.base_move_range
          if range_min == actor.base_move_range + actor.attack_skill_range
            range_min -= actor.base_move_range
          end
        end
        case range_max
        when 0
          positions.push([actor.x, actor.y])       
        else
          positions.push([actor.x, actor.y]) #starting position
          th = check_th(actor.x, actor.y)
          for position in @move_positions
            x = position[0]
            y = position[1]
            #cross pattern add stuff
            #    #
            #   ###
            #    #
            for ox in (range_min+1)..(range_max)
              positions.push([x - ox, y]) unless !valid?(actor.x - ox, actor.y) or positions.include?([x - ox, y])
              positions.push([x + ox, y]) unless !valid?(actor.x + ox, actor.y) or positions.include?([x + ox, y])
              positions.push([x, y - ox]) unless !valid?(actor.x, actor.y - ox) or positions.include?([x, y - ox])
              positions.push([x, y + ox]) unless !valid?(actor.x, actor.y + ox) or positions.include?([x, y + ox])
            end
            #fill in gaps between cross for full fill
            #     #
            #    ###
            #   #####
            #    ###
            #     #
            for i in (range_min+1)..range_max-1
              it = range_max - i
              unless it < 0
                loop do
                  if $game_map.iso?
                    positions.push([x - it, y - (range_max - (it + i - 1))]) unless !valid?(x - it, y - (range_max - (it + i - 1))) or positions.include?([x - it, y - (range_max - (it + i - 1))]) or check_th(x - it, y - (range_max - (it + i - 1))) - 10 > th
                    positions.push([x - it, y + (range_max - (it + i - 1))]) unless !valid?(x - it, y + (range_max - (it + i - 1))) or positions.include?([x - it, y + (range_max - (it + i - 1))]) or check_th(x - it, y + (range_max - (it + i - 1))) - 10 > th
                    positions.push([x + it, y + (range_max - (it + i - 1))]) unless !valid?(x + it, y + (range_max - (it + i - 1))) or positions.include?([x + it, y + (range_max - (it + i - 1))]) or check_th(x + it, y + (range_max - (it + i - 1))) - 10 > th
                    positions.push([x + it, y - (range_max - (it + i - 1))]) unless !valid?(x + it, y - (range_max - (it + i - 1))) or positions.include?([x + it, y - (range_max - (it + i - 1))]) or check_th(x + it, y - (range_max - (it + i - 1))) - 10 > th
                  else
                    positions.push([x - it, y - (range_max - (it + i - 1))]) unless !valid?(x - it, y - (range_max - (it + i - 1))) or positions.include?([x - it, y - (range_max - (it + i - 1))])
                    positions.push([x - it, y + (range_max - (it + i - 1))]) unless !valid?(x - it, y + (range_max - (it + i - 1))) or positions.include?([x - it, y + (range_max - (it + i - 1))])
                    positions.push([x + it, y + (range_max - (it + i - 1))]) unless !valid?(x + it, y + (range_max - (it + i - 1))) or positions.include?([x + it, y + (range_max - (it + i - 1))])
                    positions.push([x + it, y - (range_max - (it + i - 1))]) unless !valid?(x + it, y - (range_max - (it + i - 1))) or positions.include?([x + it, y - (range_max - (it + i - 1))])
                  end
                  it -= 1
             
                  break if it == 0
                end
              end
            end
          end
        end
      elsif range_max > -1 and type == "move"
        case range_max
        when 0
          positions.push([actor.x, actor.y])
          return positions
        else
          positions.push([actor.x, actor.y])              #push starting position
          start_move = true
          route = [[]]                                    #initialize route
          cost = [0]                                      #start position cost = 0
          more_step = [0]                                 #initialize array
          for i in more_step                              #each step in position
            x = positions[i][0]                           #set x for index
            y = positions[i][1]                           #set y for index
            c = cost[i]                                   #set cost for current postion index
            th = check_th(x,y)                            #get current tile height
           
            if actor.passable?(x, y, 2)                   #if can pass down?
              tt = $game_map.terrain_tag(x, y + 1)         #get terrain tag
              if tt > 4                                   #is terrain tag less than 4?
                tt = 0                                    #else, tt = o
              end
              nth = check_th(x, y+1)                      #get new tile height
              if c+1+tt <= range_max                      #if current route cost + 1 + terrain tag value <= move_range
                if positions.include?([x, y + 1])         #if up already found? (yes)
                  index = positions.index([x, y + 1])     #set index for position
                  unless index == i
                    if cost[index] > c+1+tt                 #is new route found less costly?
                      route[index].clear                    #reset existing route
                      route[index] = route[i] + [2]         #set new route
                      cost[index] = c+1+tt                  #replace cost table for pos
                    elsif cost[index] == c+1+tt             #is new route just as costly?
                      if rand(2) == 0                       #randomly replace, 1/3 chance
                        route[index].clear
                        route[index] = route[i] + [2]       #replace route
                        cost[index] = c+1+tt                #replace cost table for pos
                      end
                    end
                  end
                else                                      #up not found..
                  positions.push([x, y + 1])              #add position to positions array
                  route.push(route[i] + [2])              #add route for position
                  cost.push(c+1+tt)                       #add cost required for position
                  if route[i].size + 1 < range_max         #can one more step?
                    more_step.push(route.index(route[i] + [2])) #push more step for position
                  end
                end
              end
            end
             
            #comments repeat for each direction
            if actor.passable?(x, y, 4) #left
              tt = $game_map.terrain_tag(x - 1,y)
              if tt > 4
                tt = 0
              end
              nth = check_th(x, y+1)                      #get new tile height
              if c+1+tt <= range_max               
                if positions.include?([x - 1, y])
                  index = positions.index([x - 1, y])
                  if cost[index] > c+1+tt
                    route[index].clear
                    route[index] = route[i] + [4]
                    cost[index] = c+1+tt
                  elsif cost[index] == c+1+tt
                    if rand(2) == 0
                      route[index].clear
                      route[index] = route[i] + [4]
                      cost[index] = c+1+tt
                    end
                  end
                else
                  positions.push([x - 1, y])
                  route.push(route[i] + [4])
                  cost.push(c+1+tt)
                  if c+1+tt < range_max
                    more_step.push(route.index(route[i] + [4]))
                  end
                end     
              end
            end
           
            if actor.passable?(x, y, 6) #right
              tt = $game_map.terrain_tag(x + 1,y)
              if tt > 4
                tt = 0
              end
              nth = check_th(x, y+1)                      #get new tile height
              if c+1+tt <= range_max
                if positions.include?([x + 1, y])
                  index = positions.index([x + 1, y])
                  if cost[index] > c+1+tt
                    route[index].clear
                    route[index] = route[i] + [6]
                    cost[index] = c+1+tt
                  elsif cost[index] == c+1+tt
                    if rand(2) == 0
                      route[index].clear
                      route[index] = route[i] + [6]
                      cost[index] = c+1+tt
                    end
                  end
                else
                  positions.push([x + 1, y])
                  route.push(route[i] + [6])
                  cost.push(c+1+tt)
                  if c+1+tt < range_max
                    more_step.push(route.index(route[i] + [6]))
                  end
                end
              end
            end
           
            if actor.passable?(x, y, 8) #Up
              tt = $game_map.terrain_tag(x,y - 1) #get terrain tag
              if tt > 4 #is terrain tag less than 4?
                tt = 0 #else, tt = o
              end
              nth = check_th(x, y-1)                      #get new tile height
              if c+1+tt <= range_max #if current route cost + 1 + terrain tag value <= move_range
                if positions.include?([x, y - 1]) #if up already found? (yes)
                  index = positions.index([x, y - 1])
                  if cost[index] > c+1+tt #is new route found less costly?
                    route[index].clear
                    route[index] = route[i] + [8] #replace route
                    cost[index] = c+1+tt       #update cost table for pos
                  elsif cost[index] == c+1+tt #is new route just as costly?
                    if rand(3) == 0 #randomly replace, 1/3 chance
                      route[index].clear
                      route[index] = route[i] + [8] #replace route
                      cost[index] = c+1+tt     #replace cost table for pos
                    end
                  end
                else    #up not found..
                  positions.push([x, y - 1]) #add position to positions array
                  route.push(route[i] + [8]) #add route for position
                  cost.push(c+1+tt) #add cost required for position
                  if c+1+tt < range_max #can one more step?
                    more_step.push(route.index(route[i] + [8])) #push more step for position
                  end
                end
              end
            end
            if start_move
              start_move = false
            end
            #--------------------------------------------------------------
            # Old path finding method
            #--------------------------------------------------------------
            #if actor.passable?(x, y, 8) #!positions.include?([x, y - 1]) and
            #  positions.push([x, y - 1])
            #  route.push(route[i] + [8])
            #  if route[i].size + 1 < range_max
            #    more_step.push(route.index(route[i] + [8]))
            #  end
            #end
          end
        end
        need_del = [] #initialize need_del array
        for pos in positions #check all positions
          if occupied?(pos[0], pos[1]) #position occupied?
            r = route[positions.index(pos)] #read route for position
            need_del.push([pos, r]) #add position and route to array for deletion
          end         
        end
        if need_del.size > 0 #if array size > 0
          loop do #run loop
            p = need_del[0][0] #read path
            r = need_del[0][1] #read route
            route.delete(r) #delete route
            positions.delete(p) #delete path
            need_del.delete([p,r]) #update need_del array
            if need_del.size == 0 #if need_del == 0
              break  #break loop
            end
          end
        end
        @route = route #set route as instance variable instead of local only.
      elsif range_max > -1 and type == "attack"
        if @move_positions.nil?
          @move_positions = [[actor.x, actor.y]]
        end
        if @move_positions.size > 1
          range_max -= actor.base_move_range if override == false
        end
        for position in @move_positions
          x = position[0]
          y = position[1]
          if range_max == 0 and range_min == 0
            positions.push([x, y])
          end
          for ox in (range_min+1)..(range_max)           
            positions.push([x - ox, y]) unless positions.include?([x - ox, y]) or !valid?(x - ox, y)
            positions.push([x + ox, y]) unless positions.include?([x + ox, y]) or !valid?(x + ox, y)
            positions.push([x, y - ox]) unless positions.include?([x, y - ox]) or !valid?(x, y - ox)
            positions.push([x, y + ox]) unless positions.include?([x, y + ox]) or !valid?(x, y + ox)
          end
        end
      elsif range_max > -1 and type == "spell"
        case range_max
        when 0
          positions.push([actor.x, actor.y])       
        else
          positions.push([actor.x, actor.y])
          for ox in (range_min+1)..(range_max)           
            positions.push([actor.x - ox, actor.y]) unless !valid?(actor.x - ox, actor.y) or positions.include?([actor.x - ox, actor.y])
            positions.push([actor.x + ox, actor.y]) unless !valid?(actor.x + ox, actor.y) or positions.include?([actor.x + ox, actor.y])
            positions.push([actor.x, actor.y - ox]) unless !valid?(actor.x, actor.y - ox) or positions.include?([actor.x, actor.y - ox])
            positions.push([actor.x, actor.y + ox]) unless !valid?(actor.x, actor.y + ox) or positions.include?([actor.x, actor.y + ox])
          end
          for i in (range_min+1)..range_max-1
            it = range_max - i
            unless it < 0
              loop do               
                positions.push([actor.x - it, actor.y - (range_max - (it + i - 1))]) unless !valid?(actor.x - it, actor.y - (range_max - (it + i - 1))) or positions.include?([actor.x - it, actor.y - (range_max - (it + i - 1))])
                positions.push([actor.x - it, actor.y + (range_max - (it + i - 1))]) unless !valid?(actor.x - it, actor.y + (range_max - (it + i - 1))) or positions.include?([actor.x - it, actor.y + (range_max - (it + i - 1))])
                positions.push([actor.x + it, actor.y + (range_max - (it + i - 1))]) unless !valid?(actor.x + it, actor.y + (range_max - (it + i - 1))) or positions.include?([actor.x + it, actor.y + (range_max - (it + i - 1))])
                positions.push([actor.x + it, actor.y - (range_max - (it + i - 1))]) unless !valid?(actor.x + it, actor.y - (range_max - (it + i - 1))) or positions.include?([actor.x + it, actor.y - (range_max - (it + i - 1))])
               
                it -= 1
                break if it == 0
              end
            end
          end
        end
      elsif range_max > -1 and type == "bow"
        #if range_max == actor.weapon_range[0] + actor.base_move_range
        #  range_max -= actor.base_move_range
        #  range_min -= actor.base_move_range
        #end
        #p range_max
        case range_max
        when 0
          positions.push([actor.x, actor.y])
        else
          all_pos = []
          for position in @move_positions
            ox = position[0]
            oy = position[1]
            if range_max == 0 and range_min == 0
              positions.push([ox, oy])
            end
            positions = []
            positions2 = []
            positions.push([ox, oy])
            route = [[]]
            more_step = [0]
            for i in more_step
              x = positions[i][0]
              y = positions[i][1]
              th = check_th(ox,oy)
              if !positions.include?([x, y + 1]) and $game_map.valid?(x, y + 1)
                positions.push([x, y + 1])
                route.push(route[i] + [2])
                if route[i].size + 1 < range_max
                  more_step.push(route.index(route[i] + [2]))
                end
              end
              if !positions.include?([x - 1, y]) and $game_map.valid?(x - 1, y)               
                positions.push([x - 1, y])
                route.push(route[i] + [4])
                if route[i].size + 1 < range_max
                  more_step.push(route.index(route[i] + [4]))
                end
              end
              if !positions.include?([x + 1, y]) and $game_map.valid?(x + 1, y)
                positions.push([x + 1, y])
                route.push(route[i] + [6])
                if route[i].size + 1 < range_max
                  more_step.push(route.index(route[i] + [6]))
                end
              end
              if !positions.include?([x, y - 1]) and $game_map.valid?(x, y - 1)
                positions.push([x, y - 1])
                route.push(route[i] + [8])
                if route[i].size + 1 < range_max
                  more_step.push(route.index(route[i] + [8]))
                end
              end
            end
            positions2.push([ox, oy])
            route2 = [[]]
            more_step2 = [0]
            if range_min != 0
            for i in more_step2
              x = positions2[i][0]
              y = positions2[i][1]
              if !positions2.include?([x, y + 1]) and $game_map.valid?(x, y + 1)
                positions2.push([x, y + 1])
                route2.push(route2[i] + [2])
                if route2[i].size + 1 < range_min
                  more_step2.push(route2.index(route2[i] + [2]))
                end
              end
              if !positions2.include?([x - 1, y]) and $game_map.valid?(x - 1, y )
                positions2.push([x - 1, y])
                route2.push(route2[i] + [4])
                if route2[i].size + 1 < range_min
                  more_step2.push(route2.index(route2[i] + [4]))
                end
              end
              if !positions2.include?([x + 1, y]) and $game_map.valid?(x + 1, y )
                positions2.push([x + 1, y])
                route2.push(route2[i] + [6])
                if route2[i].size + 1 < range_min
                  more_step2.push(route2.index(route2[i] + [6]))
                end
              end
              if !positions2.include?([x, y - 1]) and $game_map.valid?(x, y - 1)
                positions2.push([x, y - 1])
                route2.push(route2[i] + [8])
                if route2[i].size + 1 < range_min
                  more_step2.push(route2.index(route2[i] + [8]))
                end
              end
            end
            end#end range min 0 check
            for pos in positions2
              if positions.include?(pos)
                positions.delete(pos)
              end
            end
            for pos in positions
              if !all_pos.include?(pos)
                all_pos.push(pos)
              end
            end
          end
          positions = all_pos
        end
      end
    end
    return positions
  end
[/spoiler]

Grafikal

Quote from: da good king on May 02, 2009, 08:07:01 AM
so far there are no TBSs out since GTBS,

yes there is. by the same guy. He made it for VX too. I had it for a while, but i got rid of it since I didn't have the resources for it and i didn't feel like making the resource for it. it worked fine. it was also isometric.

also, even tho this is a complicated script for probably yourself (as you said you are fairly new), i wouldn't give up on this, but i also wouldn't make this your priority. Just make other scripts and learn more while making this in the background adding new things you've learned. never the less, a non isometric TBS would be pretty cool so good luck on making this :)

modern algebra

Yeah, I don't know if I would want to start out with a TBS. I'm kind of thinking of making a TBS for VX, but I probably wouldn't release it publicly. As for calculating that, I don't see why it should be a 400 line method. Well, I sort of do, but you can use other scripts to help you out. A) My pathfinding script could be adapted for this purpose, and B) I think KGC made a terrain tag script which could be used for slowdown and stuff. Anyway, good luck.

da good king

 Thanks for all the good advice :) I'll search that pathfinding script as I too was skeptical of calc_pos's length (I starting reading the whole thing to rap my mind around the logic, but there were too many unrecognized variables that I somehow couldn't find their definition in his 20+ scripts...

If I wasn't so sure I wanted a TBS, I'd probably change up :P After playing a certain Wii Fire Emblem however, I'm certain I want to make one soon if not now. Alot of things lacked in that game.) I'm still working out a few decisions, but I think leaving this for now and coming back later will be the best course to take, as I'll soon have summer break to get some free time for this :d