Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrating Jumper in TrAinsported #15

Closed
mxub opened this issue Jul 20, 2013 · 12 comments
Closed

Integrating Jumper in TrAinsported #15

mxub opened this issue Jul 20, 2013 · 12 comments

Comments

@mxub
Copy link

mxub commented Jul 20, 2013

Hi there I'm trying to connect the Jumper library with the programming game trAInsported but I'm unable to get the require 'foo.bar' thing working .. is this a known issue or am I just to stupid ?

@Yonaba
Copy link
Owner

Yonaba commented Jul 20, 2013

Maybe you can be more explicit about the exact problem (error message), or show the relevant part of your code ?

@mxub
Copy link
Author

mxub commented Jul 20, 2013

hey thanks for the fast response :)
In trAInsporting everything happens in the AI folder. So I copied the the jumper-folder in there and created a new AI:

Grid = require 'jumper.grid'
PF = require 'jumper.pathfinder'

function ai.init(map, money)
  local walkable = function(v) return v == 'C' end
  local grid = Grid(map)
  local finder = PF(grid, 'ASTAR',walkable)
  finder:annotateGrid()

  for y = 1, #map do
    local s = ''
    for x = 1, #map[y] do
      local node = grid:getNodeAt(x,y)
      s = (s .. ' ' .. node:getClearance(walkable))
    end
    print(s)
  end
end

but when I start with that I get the following error: no such file or directory when I replace the . with / it works but the the variable is nil

EDIT

I guess it's a problem with the implementation of trAInsported's require ... but I have to work with this version so maybe you have an idea for a workaround ?

@Yonaba
Copy link
Owner

Yonaba commented Jul 20, 2013

I see what's going on here. This is simply due to the way trAinsported handle Ai files. For security reasons, the game emulates a sandbox, inside which some native Lua functions were redefined.
require is supported inside the sandbox, but it acts as a shortcut to dofile, which is just supposed to execute a chunk but not to return anything. That's the reason why you get a nil as a return value.

Well, that said, it won't be that hard to workaround that. Instead of having multiple files, i'll have to pack the whole module (set of files) into a single file, and expose some parts of its API into the global environment, so that they will be imported when using the require function in the game sandbox. Unfortunately, there's no way to do it straight, as it might require to tweak a bit the source code.

I'll be taking a closer look at it, as soon as I can manage to find some spare time.
I will probably set this on a different development branch in this repository.

@mxub
Copy link
Author

mxub commented Jul 20, 2013

I will have a closer look too :-) but thanks a lot 
~ Max

On Sat, Jul 20, 2013 at 1:55 PM, Roland Y. notifications@github.com
wrote:

I see what's going on here. This is simply due to the way trAinsported handle Ai files. For security reasons, the game emulates a sandbox, inside which some native Lua functions were redefined.
require is supported inside the sandbox, but it acts as a shortcut to dofile, which is just supposed to execute a chunk but not to return anything. That's the reason why you get a nil as a return value.
Well, that said, it won't be that hard to workaround that. Instead of having multiple files, i'll have to pack the whole module (set of files) into a single file, and expose some parts of its API into the global environment, so that they will be imported when using the require function in the game sandbox. Unfortunately, there's no way to do it straight, as it might require to tweak a bit the source code.
I'll be taking a closer look at it, as soon as I can manage to find some spare time.

I will probably set this on a different development branch in this repository.

Reply to this email directly or view it on GitHub:
#15 (comment)

@Yonaba
Copy link
Owner

Yonaba commented Jul 21, 2013

@maxxst : Just pushed a patch into a new branch of the repository.
See commit 80b05da.
Don't forget to take a quick look at the Readme, more precisely to the example of use.
How is that working for you ?

@mxub
Copy link
Author

mxub commented Jul 21, 2013

thanks for your work I will have a look later today

you are the best :D

@mxub
Copy link
Author

mxub commented Jul 21, 2013

sadly

require '_jumper/jumper.lua'
function ai.init(map, money)
  -- Simple check to assert if Jumper was successfully imported
  assert(Jumper and type(Jumper) == 'table', 'Error loading the Jumper module')

  local walkable = function(v) return v == 'C' end

  -- Library setup
  local Grid = Jumper.Grid -- Alias to the Grid submodule
  local Pathfinder = Jumper.Pathfinder -- Alias to the Pathfinder submodule


  local grid = Grid(map)
  -- Creates a pathfinder object using Jump Point Search
  local myFinder = Pathfinder(grid, 'JPS', walkable) 

  -- Define start and goal locations coordinates
  local startx, starty = 1,1
  local endx, endy = 5,1

  -- Calculates the path, and its length
  local path = myFinder:getPath(startx, starty, endx, endy)
  if path then
    print(('Path found! Length: %.2f'):format(path:getLength()))
      for node, count in path:nodes() do
        print(('Step: %d - x: %d - y: %d'):format(count, node.x, node.y))
      end
  end
end

produces the following error:
attempt to call local 'setmetatable' (a nil value)
already in the require

Filestructure

AI
| - _jumper
| | - jumper.lua
| - jumperAI.lua

@Yonaba
Copy link
Owner

Yonaba commented Jul 21, 2013

Yes, I had a terrible feeling right after pushing this. I didn't totally fix the problem.
The thing is, trAinsported sandbox doesn't support setmetatable or getmetatable functions. I should have expected that, as they are unsecure. That's the reason why it fails to load the module.

The problem is, due to the way Jumper is organized, and due to the fact it has to return objects to the user and facilities to manipulate them, I am using an object oriented programming style. And a lot of the code relies on those two functions (I mean (set/get)metatable) because of inheritance between internal objects/classes. I will probably have to consider emulating internally classes with my own proper subset of inheritance facilities to solve the problem. That seems very doable.

Anyway, you can work around that as of now by modifying the source code of your own copy of trAinsported, to start playing with Jumper. Just add those two lines in the file sandbox.lua after line 96 in the sandbox.createNew function.

sb.setmetatable = setmetatable
sb.getmetatable = getmetatable
sb.assert = assert

Of course, it will work only for your own copy of the game, as adding this would break the sandboxing security. But as I said, it's a workaround :P

Note: make sure the map passed to the Grid module is actually compatible with Jumper's map. Otherwise, you might have to convert them.

@Yonaba
Copy link
Owner

Yonaba commented Jul 22, 2013

@maxxst : New commit (see 3a32dd4). Should solve the problem, hopefully.

@mxub
Copy link
Author

mxub commented Jul 23, 2013

so I used your new commit and got a later error:

attempt to compare two table values in f_min called by precolate_up ...

@mxub
Copy link
Author

mxub commented Jul 23, 2013

i changed it to

-- Default comparison function
local function f_min(a,b)
    if type(a) == 'table' and type(b) == 'table' then
        return #a < #b
    end
    return a < b
end

seems to work now

but I have no idea what I am doing xD

@Yonaba
Copy link
Owner

Yonaba commented Jul 23, 2013

Oh, silly me, I fixed it. The comparison should be based on the F-cost property.

@Yonaba Yonaba closed this as completed Sep 18, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants