function world = makeWorld(worldSize,goals,boundary)

%state space is rectangular lattice
%<size> is vector giving size of state space on each dimension
%<goals> is list of states (by row) with special reward on entering (given in final column) 
%<boundary> is penalty for hitting boundary

%<world> is array of size [size |A|] where |A| = 2d is number of actions 
%actions are ordered down1 up1 down2 up2 etc.
%entries of <world> are rewards for all state-action pairs

D = length(worldSize); %number of dimensions
if size(goals,2)~=D+1
    error('input dimensionalities do not match')
end

%initialize reward matrix
world = zeros([worldSize 2*D]);

%set special rewards for reaching goals
for g=1:size(goals,1)
    for dim=1:D
        for delta = [-1 1] %define adjacent state by moving delta along dimension dim
            if goals(g,dim)+delta>=1 && goals(g,dim)+delta<=worldSize(dim) %adjacent state is in world
                action = dim*2 - (1+delta)/2; %action for moving from baseState to goal state
                baseState = [goals(g,1:dim-1) goals(g,dim)+delta goals(g,dim+1:D)]; %coordinates of adjacent state
                world = setReward(world,baseState,action,goals(g,end));
            end
        end
    end
end

%set rewards for hitting boundary
if D==1
    world(1,1) = boundary;
    world(worldSize,2) = boundary;
else %D>1
    for dim=1:D
        otherSize = [worldSize(1:dim-1) worldSize(dim+1:D)]; %size of world, omitting dimension dim
        baseCoords = ones(1,D-1); %coordinates of base state, omitting coordinate on dimension dim
        while baseCoords(D-1)<=otherSize(D-1)
            for dimCoord=[1 worldSize(dim)] %coordinate on dimension dim
                action = dim*2 - (dimCoord==1); %down (dimCoord==1) or up (dimCoord==worldSize(dim)) on dimension dim
                baseState = [baseCoords(1:dim-1) dimCoord baseCoords(dim:D-1)]; %coordinates of boundary state
                world = setReward(world,baseState,action,boundary);
            end
            baseCoords(1) = baseCoords(1)+1; %increment baseCoords
            for d=1:D-1
                if baseCoords(d)>otherSize(d) && d<D-1 %reached end; increment on next dimension. skip if on last dimension; will trigger end of while loop
                    baseCoords(d) = 1;
                    baseCoords(d+1) = baseCoords(d+1) + 1;
                end
            end
        end
    end
end

function newWorld = setReward(world,baseState,action,reward)
newWorld = world; %copy reward structure into newWorld
baseStateString = ''; %build text representation of baseState coordinates (workaround for limitations of matlab syntax)
for d=1:length(baseState)
    baseStateString = [baseStateString num2str(baseState(d)) ','];
end
eval(['newWorld(' baseStateString num2str(action) ') = ' num2str(reward) ';']); %set reward of taking action in baseState