From 9048dbd9aed2867a4af78cd5e002dc4fcd223bf2 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Sat, 10 Oct 2020 10:19:26 -0400 Subject: [PATCH 01/28] Added pickup and drop functions --- src/objects.jl | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index d5eaa2b..03700a5 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -51,6 +51,11 @@ const TURN_LEFT = TurnLeft() ##### abstract type AbstractObject end +abstract type Item <: AbstractObject end + +# Placeholder for empty inventory +struct Null <: Item end +const NULL = Null() Base.show(io::IO, x::AbstractObject) = print(io, Crayon(foreground=get_color(x), reset=true), convert(Char, x)) @@ -74,12 +79,12 @@ Door(c) = Door{c}() Base.convert(::Type{Char}, ::Door) = '⩎' get_color(::Door{C}) where C = C -struct Key{C} <: AbstractObject end +struct Key{C} <: Item end Key(c) = Key{c}() Base.convert(::Type{Char}, ::Key) = '⚷' get_color(::Key{C}) where C = C -struct Gem <: AbstractObject end +struct Gem <: Item end const GEM = Gem() Base.convert(::Type{Char}, ::Gem) = '♦' get_color(::Gem) = :magenta @@ -87,6 +92,7 @@ get_color(::Gem) = :magenta Base.@kwdef mutable struct Agent <: AbstractObject color::Symbol=:red dir::LRUD + inv::Item=NULL end function Base.convert(::Type{Char}, a::Agent) if a.dir === UP @@ -102,3 +108,25 @@ end get_color(a::Agent) = a.color get_dir(a::Agent) = a.dir set_dir!(a::Agent, d) = a.dir = d + +##### +# Pick Up and Drop +##### + +function pickup(a::Agent, o::Item) + if a.Item == NULL + a.Item = o + return true + end + return false +end + +function drop(a::Agent) + if a.item != NULL + x = a.item + a.item = NULL + return x + end + return nothing +end + From cf1963567792326ffa95d82f7b04b62540430bd9 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Sat, 10 Oct 2020 10:27:49 -0400 Subject: [PATCH 02/28] added pickup() dispatch for non-item objects --- src/objects.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/objects.jl b/src/objects.jl index 03700a5..635ab72 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -120,6 +120,7 @@ function pickup(a::Agent, o::Item) end return false end +pickup(a::Agent, o::AbstractObject) = nothing function drop(a::Agent) if a.item != NULL From a55e8a2c6b519d48a175e59ac6f36b9622ff24d9 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Sat, 10 Oct 2020 10:39:01 -0400 Subject: [PATCH 03/28] changed to use pickup function --- src/envs/doorkey.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/envs/doorkey.jl b/src/envs/doorkey.jl index 16ae961..b61880d 100644 --- a/src/envs/doorkey.jl +++ b/src/envs/doorkey.jl @@ -6,7 +6,6 @@ mutable struct DoorKey{W<:GridWorldBase} <: AbstractGridWorld world::W agent_pos::CartesianIndex{2} agent::Agent - has_key::Bool end function DoorKey(;n=8, agent_start_pos=CartesianIndex(2,2), rng=Random.GLOBAL_RNG) @@ -41,13 +40,14 @@ function (w::DoorKey)(::MoveForward) dest = dir(w.agent_pos) if w.world[Key(:yellow), dest] - w.has_key = true - w.world[Key(:yellow), dest] = false - w.world[EMPTY, dest] = true + if pickup(w.agent, Key(:yellow)) + w.world[Key(:yellow), dest] = false + w.world[EMPTY, dest] = true + end w.agent_pos = dest - elseif w.world[Door(:yellow), dest] && w.has_key + elseif w.world[Door(:yellow), dest] && w.agent.inv == Key(:yellow) w.agent_pos = dest - elseif w.world[Door(:yellow), dest] && !w.has_key + elseif w.world[Door(:yellow), dest] && w.agent.inv == Key(:yellow) nothing elseif dest ∈ CartesianIndices((size(w.world, 2), size(w.world, 3))) && !w.world[WALL,dest] w.agent_pos = dest From a96646a789d58cf3b5328b104d9c4ee1d6dd8db1 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Sat, 10 Oct 2020 10:51:49 -0400 Subject: [PATCH 04/28] fixed missed argument change --- src/envs/doorkey.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/envs/doorkey.jl b/src/envs/doorkey.jl index b61880d..d561116 100644 --- a/src/envs/doorkey.jl +++ b/src/envs/doorkey.jl @@ -32,7 +32,7 @@ function DoorKey(;n=8, agent_start_pos=CartesianIndex(2,2), rng=Random.GLOBAL_RN world[EMPTY, key_pos] = false world[Key(:yellow), key_pos] = true - DoorKey(world, agent_start_pos, Agent(dir=RIGHT),false) + DoorKey(world, agent_start_pos, Agent(dir=RIGHT)) end function (w::DoorKey)(::MoveForward) From bdc2a92256895865b63fc13178a37755a58ad4ff Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Sat, 10 Oct 2020 12:18:41 -0400 Subject: [PATCH 05/28] fixed wrong attribute name --- src/objects.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index 635ab72..0a7bd68 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -114,8 +114,8 @@ set_dir!(a::Agent, d) = a.dir = d ##### function pickup(a::Agent, o::Item) - if a.Item == NULL - a.Item = o + if a.inv == NULL + a.inv = o return true end return false @@ -123,9 +123,9 @@ end pickup(a::Agent, o::AbstractObject) = nothing function drop(a::Agent) - if a.item != NULL - x = a.item - a.item = NULL + if a.inv != NULL + x = a.inv + a.inv = NULL return x end return nothing From 4dd1670abc741ce3c881d92657c7e9cdbdb8c3bf Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Sat, 10 Oct 2020 12:42:52 -0400 Subject: [PATCH 06/28] fixed bug allowing passage through door w/o key --- src/envs/doorkey.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/envs/doorkey.jl b/src/envs/doorkey.jl index d561116..9683f6a 100644 --- a/src/envs/doorkey.jl +++ b/src/envs/doorkey.jl @@ -47,7 +47,7 @@ function (w::DoorKey)(::MoveForward) w.agent_pos = dest elseif w.world[Door(:yellow), dest] && w.agent.inv == Key(:yellow) w.agent_pos = dest - elseif w.world[Door(:yellow), dest] && w.agent.inv == Key(:yellow) + elseif w.world[Door(:yellow), dest] && w.agent.inv != Key(:yellow) nothing elseif dest ∈ CartesianIndices((size(w.world, 2), size(w.world, 3))) && !w.world[WALL,dest] w.agent_pos = dest From 0d6c5a19d9d0ec94f619470496a4c3769e569ba9 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Sun, 11 Oct 2020 14:53:40 -0400 Subject: [PATCH 07/28] replaced NULL with `nothing` --- src/objects.jl | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index 0a7bd68..c3b5306 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -53,10 +53,6 @@ const TURN_LEFT = TurnLeft() abstract type AbstractObject end abstract type Item <: AbstractObject end -# Placeholder for empty inventory -struct Null <: Item end -const NULL = Null() - Base.show(io::IO, x::AbstractObject) = print(io, Crayon(foreground=get_color(x), reset=true), convert(Char, x)) struct Empty <: AbstractObject end @@ -92,7 +88,7 @@ get_color(::Gem) = :magenta Base.@kwdef mutable struct Agent <: AbstractObject color::Symbol=:red dir::LRUD - inv::Item=NULL + inv::Union{Item, Nothing} end function Base.convert(::Type{Char}, a::Agent) if a.dir === UP @@ -114,7 +110,7 @@ set_dir!(a::Agent, d) = a.dir = d ##### function pickup(a::Agent, o::Item) - if a.inv == NULL + if a.inv == nothing a.inv = o return true end @@ -123,9 +119,9 @@ end pickup(a::Agent, o::AbstractObject) = nothing function drop(a::Agent) - if a.inv != NULL + if a.inv != nothing x = a.inv - a.inv = NULL + a.inv = nothing return x end return nothing From 922529c8fbb48e6090ee3f6d3a358a1b1ead5951 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Mon, 12 Oct 2020 08:32:34 -0400 Subject: [PATCH 08/28] Added trait-based implementation of pickup --- src/objects.jl | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index c3b5306..4bb4438 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -51,7 +51,6 @@ const TURN_LEFT = TurnLeft() ##### abstract type AbstractObject end -abstract type Item <: AbstractObject end Base.show(io::IO, x::AbstractObject) = print(io, Crayon(foreground=get_color(x), reset=true), convert(Char, x)) @@ -75,12 +74,12 @@ Door(c) = Door{c}() Base.convert(::Type{Char}, ::Door) = '⩎' get_color(::Door{C}) where C = C -struct Key{C} <: Item end +struct Key{C} <: AbstractObject end Key(c) = Key{c}() Base.convert(::Type{Char}, ::Key) = '⚷' get_color(::Key{C}) where C = C -struct Gem <: Item end +struct Gem <: AbstractObject end const GEM = Gem() Base.convert(::Type{Char}, ::Gem) = '♦' get_color(::Gem) = :magenta @@ -88,7 +87,7 @@ get_color(::Gem) = :magenta Base.@kwdef mutable struct Agent <: AbstractObject color::Symbol=:red dir::LRUD - inv::Union{Item, Nothing} + inv::Union{AbstractObject, Nothing}=nothing end function Base.convert(::Type{Char}, a::Agent) if a.dir === UP @@ -109,14 +108,23 @@ set_dir!(a::Agent, d) = a.dir = d # Pick Up and Drop ##### -function pickup(a::Agent, o::Item) +struct Item end +struct Nonitem end +const ITEM = Item() +const NONITEM = Nonitem() +isitem(::Type{Key{T}}) where T = ITEM +isitem(::Type{Gem}) = ITEM +isitem() = NONITEM + +pickup(a::Agent, o::T) where T = pickup(isitem(T), a, o) +function pickup(::Item, a::Agent, o::AbstractObject) if a.inv == nothing a.inv = o return true end return false end -pickup(a::Agent, o::AbstractObject) = nothing +pickup(a::Agent, ::Nonitem, o::AbstractObject) = nothing function drop(a::Agent) if a.inv != nothing From 26b536dd695c507ecc780abb9c025dd71c88a776 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Mon, 12 Oct 2020 08:54:00 -0400 Subject: [PATCH 09/28] Made pickup and drop functors --- src/envs/doorkey.jl | 2 +- src/objects.jl | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/envs/doorkey.jl b/src/envs/doorkey.jl index 9683f6a..4d6a4e6 100644 --- a/src/envs/doorkey.jl +++ b/src/envs/doorkey.jl @@ -40,7 +40,7 @@ function (w::DoorKey)(::MoveForward) dest = dir(w.agent_pos) if w.world[Key(:yellow), dest] - if pickup(w.agent, Key(:yellow)) + if PICKUP(w.agent, Key(:yellow)) w.world[Key(:yellow), dest] = false w.world[EMPTY, dest] = true end diff --git a/src/objects.jl b/src/objects.jl index 4bb4438..621a074 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -116,7 +116,10 @@ isitem(::Type{Key{T}}) where T = ITEM isitem(::Type{Gem}) = ITEM isitem() = NONITEM -pickup(a::Agent, o::T) where T = pickup(isitem(T), a, o) +struct Pickup end +const PICKUP = Pickup() + +(::Pickup)(a::Agent, o::T) where T = pickup(isitem(T), a, o) function pickup(::Item, a::Agent, o::AbstractObject) if a.inv == nothing a.inv = o @@ -126,7 +129,10 @@ function pickup(::Item, a::Agent, o::AbstractObject) end pickup(a::Agent, ::Nonitem, o::AbstractObject) = nothing -function drop(a::Agent) +struct Drop end +const DROP = Drop() + +function (::Drop)(a::Agent) if a.inv != nothing x = a.inv a.inv = nothing From 50fb8ca9820656e58779703009d57821c3ba8d45 Mon Sep 17 00:00:00 2001 From: Ben Landrum <36489943+landrumb@users.noreply.github.com> Date: Mon, 12 Oct 2020 19:29:49 -0400 Subject: [PATCH 10/28] Fix error in train implementation Co-authored-by: Jun Tian --- src/objects.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index 621a074..c009b03 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -127,7 +127,7 @@ function pickup(::Item, a::Agent, o::AbstractObject) end return false end -pickup(a::Agent, ::Nonitem, o::AbstractObject) = nothing +pickup(::Nonitem, a::Agent, o::AbstractObject) = nothing struct Drop end const DROP = Drop() @@ -140,4 +140,3 @@ function (::Drop)(a::Agent) end return nothing end - From a896252cefab06c5cc1745943832c9cf90c635df Mon Sep 17 00:00:00 2001 From: Ben Landrum <36489943+landrumb@users.noreply.github.com> Date: Mon, 12 Oct 2020 19:31:40 -0400 Subject: [PATCH 11/28] added type annotation for non-item isitem() Co-authored-by: Jun Tian --- src/objects.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objects.jl b/src/objects.jl index c009b03..ed61ae3 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -114,7 +114,7 @@ const ITEM = Item() const NONITEM = Nonitem() isitem(::Type{Key{T}}) where T = ITEM isitem(::Type{Gem}) = ITEM -isitem() = NONITEM +isitem(x::AbstractObject) = isitem(typeof(x)) struct Pickup end const PICKUP = Pickup() From e511da04748f41436271b7512172bfdb7227eee6 Mon Sep 17 00:00:00 2001 From: Ben Landrum <36489943+landrumb@users.noreply.github.com> Date: Mon, 12 Oct 2020 19:33:43 -0400 Subject: [PATCH 12/28] made key annotation in isitem trait cleaner Co-authored-by: Jun Tian --- src/objects.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objects.jl b/src/objects.jl index ed61ae3..0f6a5b3 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -112,7 +112,7 @@ struct Item end struct Nonitem end const ITEM = Item() const NONITEM = Nonitem() -isitem(::Type{Key{T}}) where T = ITEM +isitem(::Type{<:Key}) = ITEM isitem(::Type{Gem}) = ITEM isitem(x::AbstractObject) = isitem(typeof(x)) From 849d53719e936aa31a2b531f72326ddb09841c4e Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Tue, 13 Oct 2020 06:05:55 -0400 Subject: [PATCH 13/28] moved drop functor definition to pickup definition --- src/objects.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index 0f6a5b3..0320486 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -119,6 +119,9 @@ isitem(x::AbstractObject) = isitem(typeof(x)) struct Pickup end const PICKUP = Pickup() +struct Drop end +const DROP = Drop() + (::Pickup)(a::Agent, o::T) where T = pickup(isitem(T), a, o) function pickup(::Item, a::Agent, o::AbstractObject) if a.inv == nothing @@ -129,9 +132,6 @@ function pickup(::Item, a::Agent, o::AbstractObject) end pickup(::Nonitem, a::Agent, o::AbstractObject) = nothing -struct Drop end -const DROP = Drop() - function (::Drop)(a::Agent) if a.inv != nothing x = a.inv From c9bc6e04e840459c0f1a566d4072233cbb92de21 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Tue, 13 Oct 2020 06:09:01 -0400 Subject: [PATCH 14/28] refactored item to transportable --- src/objects.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index 0320486..aa00dc6 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -108,13 +108,13 @@ set_dir!(a::Agent, d) = a.dir = d # Pick Up and Drop ##### -struct Item end -struct Nonitem end -const ITEM = Item() -const NONITEM = Nonitem() -isitem(::Type{<:Key}) = ITEM -isitem(::Type{Gem}) = ITEM -isitem(x::AbstractObject) = isitem(typeof(x)) +struct Transportable end +struct Nontransportable end +const TRANSPORTABLE = Transportable() +const NONTRANSPORTABLE = Nontransportable() +istransportable(::Type{<:Key}) = TRANSPORTABLE +istransportable(::Type{Gem}) = TRANSPORTABLE +istransportable(x::AbstractObject) = istransportable(typeof(x)) struct Pickup end const PICKUP = Pickup() @@ -122,15 +122,15 @@ const PICKUP = Pickup() struct Drop end const DROP = Drop() -(::Pickup)(a::Agent, o::T) where T = pickup(isitem(T), a, o) -function pickup(::Item, a::Agent, o::AbstractObject) +(::Pickup)(a::Agent, o::T) where T = pickup(istransportable(T), a, o) +function pickup(::Transportable, a::Agent, o::AbstractObject) if a.inv == nothing a.inv = o return true end return false end -pickup(::Nonitem, a::Agent, o::AbstractObject) = nothing +pickup(::Nontransportable, a::Agent, o::AbstractObject) = nothing function (::Drop)(a::Agent) if a.inv != nothing From a774ece30e67afbbe18796952b462d8aa0555f45 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Tue, 13 Oct 2020 06:30:53 -0400 Subject: [PATCH 15/28] added array_agent --- src/objects.jl | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index aa00dc6..0f8bb29 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -84,12 +84,24 @@ const GEM = Gem() Base.convert(::Type{Char}, ::Gem) = '♦' get_color(::Gem) = :magenta -Base.@kwdef mutable struct Agent <: AbstractObject +abstract type AbstractAgent <: AbstractObject end + +Base.@kwdef mutable struct Agent <: AbstractAgent color::Symbol=:red dir::LRUD inv::Union{AbstractObject, Nothing}=nothing end -function Base.convert(::Type{Char}, a::Agent) + +Base.@kwdef mutable struct Array_agent <: AbstractAgent + color::Symbol=:red + dir::LRUD + inv::Vector{Union{AbstractObject, Nothing}}=[] +end +function Array_agent(dir::LRUD, len::Integer; color::Symbol=:red) + Array_agent(color, dir, Vector{Union{AbstractObject, Nothing}}(nothing, len)) +end + +function Base.convert(::Type{Char}, a::AbstractAgent) if a.dir === UP '↑' elseif a.dir === DOWN @@ -100,9 +112,9 @@ function Base.convert(::Type{Char}, a::Agent) '→' end end -get_color(a::Agent) = a.color -get_dir(a::Agent) = a.dir -set_dir!(a::Agent, d) = a.dir = d +get_color(a::AbstractAgent) = a.color +get_dir(a::AbstractAgent) = a.dir +set_dir!(a::AbstractAgent, d) = a.dir = d ##### # Pick Up and Drop From 8fe68296e580a8aba647d21b860759b4f1eab4be Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Tue, 13 Oct 2020 06:53:40 -0400 Subject: [PATCH 16/28] implemented pickup and drop for array_agent --- src/objects.jl | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index 0f8bb29..37d9dc7 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -134,15 +134,24 @@ const PICKUP = Pickup() struct Drop end const DROP = Drop() -(::Pickup)(a::Agent, o::T) where T = pickup(istransportable(T), a, o) -function pickup(::Transportable, a::Agent, o::AbstractObject) +(::Pickup)(a::AbstractAgent, o::T) where T = PICKUP(istransportable(T), a, o) +function (::Pickup)(::Transportable, a::Agent, o::AbstractObject) if a.inv == nothing a.inv = o return true end return false end -pickup(::Nontransportable, a::Agent, o::AbstractObject) = nothing +function (::Pickup)(::Transportable, a::Array_agent, o::AbstractObject) + for (i, v) in enumerate(a.inv) # Picked up objects go into the first empty index + if v == nothing + a.inv[i] = o + return true + end + end + return false +end +pickup(::Nontransportable, a::AbstractAgent, o::AbstractObject) = nothing function (::Drop)(a::Agent) if a.inv != nothing @@ -152,3 +161,12 @@ function (::Drop)(a::Agent) end return nothing end +function (::Drop)(a::Array_agent) + for (i, v) in Iterators.reverse(enumerate(a.inv)) # Most recently picked up objects are dropped first + if typeof(v)<:AbstractObject + a.inv[i] = nothing + return v + end + end + return nothing +end From 1b3efdc87419c71632613662bcababc39832d072 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Tue, 13 Oct 2020 07:00:58 -0400 Subject: [PATCH 17/28] updated export statements --- src/objects.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index 37d9dc7..d23491f 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -1,5 +1,5 @@ -export COLORS, MOVE_FORWARD, TURN_LEFT, TURN_RIGHT, UP, DOWN, LEFT, RIGHT, LRUD, EMPTY, WALL, GOAL, GEM -export MoveForward, AbstractObject, Empty, Wall, Goal, Door, Gem, Agent +export COLORS, MOVE_FORWARD, TURN_LEFT, TURN_RIGHT, UP, DOWN, LEFT, RIGHT, LRUD, EMPTY, WALL, GOAL, GEM, PICKUP, DROP +export MoveForward, AbstractObject, Empty, Wall, Goal, Door, Gem, Agent, Array_agent export get_color using Crayons From 89759ae53a46cd937606f07ec781b6863d3b1579 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Tue, 13 Oct 2020 07:09:20 -0400 Subject: [PATCH 18/28] Revert "updated export statements" This reverts commit 1b3efdc87419c71632613662bcababc39832d072. --- src/objects.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index d23491f..37d9dc7 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -1,5 +1,5 @@ -export COLORS, MOVE_FORWARD, TURN_LEFT, TURN_RIGHT, UP, DOWN, LEFT, RIGHT, LRUD, EMPTY, WALL, GOAL, GEM, PICKUP, DROP -export MoveForward, AbstractObject, Empty, Wall, Goal, Door, Gem, Agent, Array_agent +export COLORS, MOVE_FORWARD, TURN_LEFT, TURN_RIGHT, UP, DOWN, LEFT, RIGHT, LRUD, EMPTY, WALL, GOAL, GEM +export MoveForward, AbstractObject, Empty, Wall, Goal, Door, Gem, Agent export get_color using Crayons From a8dfb6dc6fc4f07b540b2e4b614e4354dca8acfe Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Tue, 13 Oct 2020 08:46:47 -0400 Subject: [PATCH 19/28] Implemented Agent as a parametric struct --- src/objects.jl | 45 ++++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/src/objects.jl b/src/objects.jl index f578270..ad411d0 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -45,26 +45,22 @@ const GEM = Gem() Base.convert(::Type{Char}, ::Gem) = '♦' get_color(::Gem) = :magenta -abstract type AbstractAgent <: AbstractObject end +const INV = Union{Nothing, AbstractObject} +const INVARRAY = Vector{Union{AbstractObject, Nothing}} -Base.@kwdef mutable struct Agent <: AbstractAgent - color::Symbol=:red +mutable struct Agent{I<:Union{INV, INVARRAY}} <: AbstractObject + color::Symbol dir::LRUD - inv::Union{AbstractObject, Nothing}=nothing + inv::I end - -Base.@kwdef mutable struct Array_agent <: AbstractAgent - color::Symbol=:red - dir::LRUD - inv::Vector{Union{AbstractObject, Nothing}}=[] -end - -function Array_agent(dir::LRUD, len::Integer; color::Symbol=:red) - Array_agent(color, dir, Vector{Union{AbstractObject, Nothing}}(nothing, len)) +Agent(dir::LRUD; inv::INV=nothing, color::Symbol=:red) = Agent{INV}(color, dir, inv) +Agent(;dir::LRUD, inv::INV=nothing, color::Symbol=:red) = Agent{INV}(color, dir, inv) +function Agent{INVARRAY}(dir::LRUD, len::Integer; color::Symbol=:red) + Agent{INVARRAY}(color, dir, INVARRAY(nothing, len)) end +Agent{INV}(dir::LRUD; inv::INV=nothing, color::Symbol=:red) = Agent{INV}(color, dir, inv) -function Base.convert(::Type{Char}, a::AbstractAgent) - +function Base.convert(::Type{Char}, a::Agent) if a.dir === UP '↑' elseif a.dir === DOWN @@ -75,10 +71,9 @@ function Base.convert(::Type{Char}, a::AbstractAgent) '→' end end - -get_color(a::AbstractAgent) = a.color -get_dir(a::AbstractAgent) = a.dir -set_dir!(a::AbstractAgent, d) = a.dir = d +get_color(a::Agent) = a.color +get_dir(a::Agent) = a.dir +set_dir!(a::Agent, d) = a.dir = d ##### # Pick Up and Drop @@ -98,15 +93,15 @@ const PICKUP = Pickup() struct Drop end const DROP = Drop() -(::Pickup)(a::AbstractAgent, o::T) where T = PICKUP(istransportable(T), a, o) -function (::Pickup)(::Transportable, a::Agent, o::AbstractObject) +(::Pickup)(a::Agent, o::T) where T = PICKUP(istransportable(T), a, o) +function (::Pickup)(::Transportable, a::Agent{INV}, o::AbstractObject) if a.inv == nothing a.inv = o return true end return false end -function (::Pickup)(::Transportable, a::Array_agent, o::AbstractObject) +function (::Pickup)(::Transportable, a::Agent{INVARRAY}, o::AbstractObject) for (i, v) in enumerate(a.inv) # Picked up objects go into the first empty index if v == nothing a.inv[i] = o @@ -115,9 +110,9 @@ function (::Pickup)(::Transportable, a::Array_agent, o::AbstractObject) end return false end -pickup(::Nontransportable, a::AbstractAgent, o::AbstractObject) = nothing +pickup(::Nontransportable, a::Agent, o::AbstractObject) = nothing -function (::Drop)(a::Agent) +function (::Drop)(a::Agent{INV}) if a.inv != nothing x = a.inv a.inv = nothing @@ -125,7 +120,7 @@ function (::Drop)(a::Agent) end return nothing end -function (::Drop)(a::Array_agent) +function (::Drop)(a::Agent{INVARRAY}) for (i, v) in Iterators.reverse(enumerate(a.inv)) # Most recently picked up objects are dropped first if typeof(v)<:AbstractObject a.inv[i] = nothing From c2daeac389709f989848f1774ae91fbc750af25e Mon Sep 17 00:00:00 2001 From: Jun Tian Date: Tue, 13 Oct 2020 22:48:00 +0800 Subject: [PATCH 20/28] slightly polish --- src/actions.jl | 6 +++ src/envs/doorkey.jl | 8 ++-- src/objects.jl | 89 ++++++++++++++++++++------------------------- 3 files changed, 50 insertions(+), 53 deletions(-) diff --git a/src/actions.jl b/src/actions.jl index 33006bd..5f30c21 100644 --- a/src/actions.jl +++ b/src/actions.jl @@ -24,3 +24,9 @@ const TURN_LEFT = TurnLeft() (x::TurnLeft)(::Up) = LEFT (x::TurnLeft)(::Right) = UP (x::TurnLeft)(::Down) = RIGHT + +struct Pickup <: AbstractGridWorldAction end +const PICK_UP = Pickup() + +struct Drop <: AbstractGridWorldAction end +const DROP = Drop() diff --git a/src/envs/doorkey.jl b/src/envs/doorkey.jl index 4d6a4e6..942d343 100644 --- a/src/envs/doorkey.jl +++ b/src/envs/doorkey.jl @@ -32,7 +32,7 @@ function DoorKey(;n=8, agent_start_pos=CartesianIndex(2,2), rng=Random.GLOBAL_RN world[EMPTY, key_pos] = false world[Key(:yellow), key_pos] = true - DoorKey(world, agent_start_pos, Agent(dir=RIGHT)) + DoorKey(world, agent_start_pos, Agent(;dir=RIGHT)) end function (w::DoorKey)(::MoveForward) @@ -45,10 +45,10 @@ function (w::DoorKey)(::MoveForward) w.world[EMPTY, dest] = true end w.agent_pos = dest - elseif w.world[Door(:yellow), dest] && w.agent.inv == Key(:yellow) - w.agent_pos = dest - elseif w.world[Door(:yellow), dest] && w.agent.inv != Key(:yellow) + elseif w.world[Door(:yellow), dest] && w.agent.inv !== Key(:yellow) nothing + elseif w.world[Door(:yellow), dest] && w.agent.inventory === Key(:yellow) + w.agent_pos = dest elseif dest ∈ CartesianIndices((size(w.world, 2), size(w.world, 3))) && !w.world[WALL,dest] w.agent_pos = dest end diff --git a/src/objects.jl b/src/objects.jl index ad411d0..08fd2fa 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -45,40 +45,34 @@ const GEM = Gem() Base.convert(::Type{Char}, ::Gem) = '♦' get_color(::Gem) = :magenta -const INV = Union{Nothing, AbstractObject} -const INVARRAY = Vector{Union{AbstractObject, Nothing}} +##### +# Agent +##### -mutable struct Agent{I<:Union{INV, INVARRAY}} <: AbstractObject +mutable struct Agent{I<:Union{Nothing, AbstractObject, Vector}} <: AbstractObject color::Symbol dir::LRUD - inv::I + inventory::I end -Agent(dir::LRUD; inv::INV=nothing, color::Symbol=:red) = Agent{INV}(color, dir, inv) -Agent(;dir::LRUD, inv::INV=nothing, color::Symbol=:red) = Agent{INV}(color, dir, inv) -function Agent{INVARRAY}(dir::LRUD, len::Integer; color::Symbol=:red) - Agent{INVARRAY}(color, dir, INVARRAY(nothing, len)) -end -Agent{INV}(dir::LRUD; inv::INV=nothing, color::Symbol=:red) = Agent{INV}(color, dir, inv) + +Agent(;dir::LRUD, inventory=nothing, color::Symbol=:red) = Agent(color, dir, inventory) function Base.convert(::Type{Char}, a::Agent) - if a.dir === UP + if a.dir === UP '↑' - elseif a.dir === DOWN + elseif a.dir === DOWN '↓' - elseif a.dir === LEFT + elseif a.dir === LEFT '←' elseif a.dir === RIGHT '→' end end + get_color(a::Agent) = a.color get_dir(a::Agent) = a.dir set_dir!(a::Agent, d) = a.dir = d -##### -# Pick Up and Drop -##### - struct Transportable end struct Nontransportable end const TRANSPORTABLE = Transportable() @@ -87,45 +81,42 @@ istransportable(::Type{<:Key}) = TRANSPORTABLE istransportable(::Type{Gem}) = TRANSPORTABLE istransportable(x::AbstractObject) = istransportable(typeof(x)) -struct Pickup end -const PICKUP = Pickup() - -struct Drop end -const DROP = Drop() - -(::Pickup)(a::Agent, o::T) where T = PICKUP(istransportable(T), a, o) -function (::Pickup)(::Transportable, a::Agent{INV}, o::AbstractObject) - if a.inv == nothing - a.inv = o - return true - end - return false -end -function (::Pickup)(::Transportable, a::Agent{INVARRAY}, o::AbstractObject) - for (i, v) in enumerate(a.inv) # Picked up objects go into the first empty index - if v == nothing - a.inv[i] = o - return true +(a::Pickup)(a::Agent, o) = a(istransportable(o), a, o) + +function (::Pickup)(::Transportable, a::Agent, o::AbstractObject) + if isnothing(a.inventory) + a.inventory = o + true + elseif a.inventory isa Vector + i = findfirst(isnothing, a.v) + if isnothing(i) + false + else + a.inventory[i] = o + true end + else + false end - return false end -pickup(::Nontransportable, a::Agent, o::AbstractObject) = nothing -function (::Drop)(a::Agent{INV}) - if a.inv != nothing +function (::Drop)(a::Agent) + if isnothing(a.inv) + nothing + elseif a.inv isa AbstractObject x = a.inv a.inv = nothing - return x - end - return nothing -end -function (::Drop)(a::Agent{INVARRAY}) - for (i, v) in Iterators.reverse(enumerate(a.inv)) # Most recently picked up objects are dropped first - if typeof(v)<:AbstractObject + x + elseif a.inv isa Vector + i = findlast(x -> x isa AbstractObject, a.inv) + if isnothing(i) + nothing + else + x = a.inv[i] a.inv[i] = nothing - return v + x end + else + @error "unknown inventory type $(a.inv)" end - return nothing end From 9c11a9c6d03adb97f2f1c27936f4a949db224024 Mon Sep 17 00:00:00 2001 From: Jun Tian Date: Tue, 13 Oct 2020 23:17:34 +0800 Subject: [PATCH 21/28] fix DoorKey --- src/envs/doorkey.jl | 4 ++-- src/objects.jl | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/envs/doorkey.jl b/src/envs/doorkey.jl index 942d343..703a268 100644 --- a/src/envs/doorkey.jl +++ b/src/envs/doorkey.jl @@ -40,12 +40,12 @@ function (w::DoorKey)(::MoveForward) dest = dir(w.agent_pos) if w.world[Key(:yellow), dest] - if PICKUP(w.agent, Key(:yellow)) + if PICK_UP(w.agent, Key(:yellow)) w.world[Key(:yellow), dest] = false w.world[EMPTY, dest] = true end w.agent_pos = dest - elseif w.world[Door(:yellow), dest] && w.agent.inv !== Key(:yellow) + elseif w.world[Door(:yellow), dest] && w.agent.inventory !== Key(:yellow) nothing elseif w.world[Door(:yellow), dest] && w.agent.inventory === Key(:yellow) w.agent_pos = dest diff --git a/src/objects.jl b/src/objects.jl index 08fd2fa..af58568 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -49,10 +49,10 @@ get_color(::Gem) = :magenta # Agent ##### -mutable struct Agent{I<:Union{Nothing, AbstractObject, Vector}} <: AbstractObject +mutable struct Agent <: AbstractObject color::Symbol dir::LRUD - inventory::I + inventory::Union{Nothing, AbstractObject, Vector} end Agent(;dir::LRUD, inventory=nothing, color::Symbol=:red) = Agent(color, dir, inventory) @@ -81,7 +81,7 @@ istransportable(::Type{<:Key}) = TRANSPORTABLE istransportable(::Type{Gem}) = TRANSPORTABLE istransportable(x::AbstractObject) = istransportable(typeof(x)) -(a::Pickup)(a::Agent, o) = a(istransportable(o), a, o) +(x::Pickup)(a::Agent, o) = x(istransportable(o), a, o) function (::Pickup)(::Transportable, a::Agent, o::AbstractObject) if isnothing(a.inventory) @@ -101,22 +101,22 @@ function (::Pickup)(::Transportable, a::Agent, o::AbstractObject) end function (::Drop)(a::Agent) - if isnothing(a.inv) + if isnothing(a.inventory) nothing - elseif a.inv isa AbstractObject - x = a.inv - a.inv = nothing + elseif a.inventory isa AbstractObject + x = a.inventory + a.inventory = nothing x - elseif a.inv isa Vector - i = findlast(x -> x isa AbstractObject, a.inv) + elseif a.inventory isa Vector + i = findlast(x -> x isa AbstractObject, a.inventory) if isnothing(i) nothing else - x = a.inv[i] - a.inv[i] = nothing + x = a.inventory[i] + a.inventory[i] = nothing x end else - @error "unknown inventory type $(a.inv)" + @error "unknown inventory type $(a.inventory)" end end From 891e588578463c0e7fe6a506f66064268a92dbce Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Fri, 16 Oct 2020 13:48:35 -0400 Subject: [PATCH 22/28] Added backend for perspective occlusion --- src/grid_world_base.jl | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/grid_world_base.jl b/src/grid_world_base.jl index cf3fb14..73e9060 100644 --- a/src/grid_world_base.jl +++ b/src/grid_world_base.jl @@ -60,6 +60,41 @@ function Random.rand(f::Function, w::GridWorldBase; max_try=typemax(Int), rng=Ra return nothing end +##### +# Occlusion +##### + +radius(x, y) = √(x^2 + y^2) +radius(p::Tuple) = radius(p[1], p[2]) +theta(x, y) = x == 0 ? sign(y)*π/2 : atan(y, x) +theta(p::Tuple{<:Real}) = theta(p[1], p[2]) + +struct PolarCoord + θ::AbstractFloat + r::AbstractFloat +end +PolarCoord(θ::AbstractFLoat, r::AbstractFLoat) = PolarCoord((θ + (r<0 && π)) % 2π, abs(r)) +PolarCoord(p::Tuple) = PolarCoord(theta(p), radius(p)) +PolarCoord(p::CartesianIndex) = PolarCoord(Tuple(p)) + +struct Shadow + minθ::AbstractFloat + maxθ::AbstractFloat + r::AbstractFloat +end +function Shadow(p::CartesianIndex) + r = radius(Tuple(p)) + corners = [(p[1]+x, p[2]+y) for x in -.5:.5, y in -.5:.5] + corners = theta.(corners) + Shadow(min(corners), max(corners), r) +end + +function (s::Shadow)(v::CartesianIndices) + polar = PolarCoord.(v) + f(x) = x.r > s.r && s.minθ < x.θ <= s.maxθ + f.(polar) +end + ##### # get_agent_view ##### From 8f47a525ddba1504a0cf5e33f325c51fb21a2caa Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Fri, 16 Oct 2020 13:52:52 -0400 Subject: [PATCH 23/28] added light docstring for shadow functor --- src/grid_world_base.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/grid_world_base.jl b/src/grid_world_base.jl index 73e9060..5d6f129 100644 --- a/src/grid_world_base.jl +++ b/src/grid_world_base.jl @@ -89,6 +89,10 @@ function Shadow(p::CartesianIndex) Shadow(min(corners), max(corners), r) end +""" +returns a 2D array of boolean values, where `true` represents an index which is +occluded by the shadow `s` evaluating `v` +""" function (s::Shadow)(v::CartesianIndices) polar = PolarCoord.(v) f(x) = x.r > s.r && s.minθ < x.θ <= s.maxθ From 08e48fa6ed8e912eacc8874d1ad30159ae3b0493 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Fri, 16 Oct 2020 19:03:56 -0400 Subject: [PATCH 24/28] Added very light test --- src/grid_world_base.jl | 9 +++++---- test/runtests.jl | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/grid_world_base.jl b/src/grid_world_base.jl index 5d6f129..e0e447e 100644 --- a/src/grid_world_base.jl +++ b/src/grid_world_base.jl @@ -67,13 +67,13 @@ end radius(x, y) = √(x^2 + y^2) radius(p::Tuple) = radius(p[1], p[2]) theta(x, y) = x == 0 ? sign(y)*π/2 : atan(y, x) -theta(p::Tuple{<:Real}) = theta(p[1], p[2]) +theta(p::Tuple) = theta(p[1], p[2]) struct PolarCoord θ::AbstractFloat r::AbstractFloat end -PolarCoord(θ::AbstractFLoat, r::AbstractFLoat) = PolarCoord((θ + (r<0 && π)) % 2π, abs(r)) +PolarCoord(θ::Real, r::Real) = PolarCoord((θ + (r<0 && π)) % 2π, abs(r)) PolarCoord(p::Tuple) = PolarCoord(theta(p), radius(p)) PolarCoord(p::CartesianIndex) = PolarCoord(Tuple(p)) @@ -86,7 +86,7 @@ function Shadow(p::CartesianIndex) r = radius(Tuple(p)) corners = [(p[1]+x, p[2]+y) for x in -.5:.5, y in -.5:.5] corners = theta.(corners) - Shadow(min(corners), max(corners), r) + Shadow(minimum(corners), maximum(corners), r) end """ @@ -95,7 +95,7 @@ occluded by the shadow `s` evaluating `v` """ function (s::Shadow)(v::CartesianIndices) polar = PolarCoord.(v) - f(x) = x.r > s.r && s.minθ < x.θ <= s.maxθ + f(x) = x.r > s.r && s.minθ <= x.θ <= s.maxθ f.(polar) end @@ -123,5 +123,6 @@ function get_agent_view!(v::AbstractArray{Bool,3}, a::AbstractArray{Bool,3}, p:: v[:, ind_map(ind.I, view_size, dir)...] .= a[:, inds[ind]] end end + v end diff --git a/test/runtests.jl b/test/runtests.jl index 8a28222..64dbf1f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -28,4 +28,21 @@ ACTIONS = [TURN_LEFT, TURN_RIGHT, MOVE_FORWARD] end end end + @testset "grid_world_base.jl" begin + grid = CartesianIndices((-3:3, 0:6)) + soln = + [[1,1,1,1,1,1,1] + [1,1,1,1,1,1,1] + [1,1,1,1,1,1,1] + [1,1,1,1,1,1,1] + [1,1,1,1,0,0,1] + [0,0,1,1,0,0,1] + [0,1,1,1,0,0,0]] + + s = GridWorlds.Shadow(CartesianIndex((1,3))) + println("minθ:$(s.minθ)|maxθ:$(s.maxθ)|r:$(s.r)") + println(s(grid)) + println("($(GridWorlds.theta(3,4)), $(GridWorlds.radius(3,4)))") + println(s(CartesianIndices((3:3, 5:5)))) + end end From 501bca030bae619d58c38ec18cffc6bea85ec1ce Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Sun, 18 Oct 2020 18:14:04 -0400 Subject: [PATCH 25/28] Implemented opacity trait --- src/grid_world_base.jl | 2 +- src/objects.jl | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/grid_world_base.jl b/src/grid_world_base.jl index e0e447e..dab7b43 100644 --- a/src/grid_world_base.jl +++ b/src/grid_world_base.jl @@ -94,7 +94,7 @@ returns a 2D array of boolean values, where `true` represents an index which is occluded by the shadow `s` evaluating `v` """ function (s::Shadow)(v::CartesianIndices) - polar = PolarCoord.(v) + polar = PolarCoord.(v)`` f(x) = x.r > s.r && s.minθ <= x.θ <= s.maxθ f.(polar) end diff --git a/src/objects.jl b/src/objects.jl index 1fb947e..5d21b2d 100644 --- a/src/objects.jl +++ b/src/objects.jl @@ -30,8 +30,10 @@ const GOAL = Goal() Base.convert(::Type{Char}, ::Goal) = '♥' get_color(::Goal) = :red -struct Door{C} <: AbstractObject end -Door(c) = Door{c}() +struct Door{C} <: AbstractObject + open::Bool +end +Door(c) = Door{c}(false) Base.convert(::Type{Char}, ::Door) = '⩎' get_color(::Door{C}) where C = C @@ -84,6 +86,16 @@ istransportable(::Type{<:Key}) = TRANSPORTABLE istransportable(::Type{Gem}) = TRANSPORTABLE istransportable(x::AbstractObject) = istransportable(typeof(x)) +struct Opaque end +struct Transparent end +const OPAQUE = Opaque() +const TRANSPARENT = Transparent() +isopaque(::Type{<:AbstractObject}) = OPAQUE +isopaque(::Type{<:Key}) = TRANSPARENT +isopaque(::Type{Gem}) = TRANSPARENT +isopaque(x::AbstractObject) = isopaque(typeof(x)) +isopaque(x<:Door) = x.open ? TRANSPARENT : OPAQUE + (x::Pickup)(a::Agent, o) = x(istransportable(o), a, o) function (::Pickup)(::Transportable, a::Agent, o::AbstractObject) From a4292af96bb151dc576a81213ab4243efaa9bbd4 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Mon, 19 Oct 2020 11:55:09 -0400 Subject: [PATCH 26/28] added light docstring for get_agent_view!() --- src/grid_world_base.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/grid_world_base.jl b/src/grid_world_base.jl index dab7b43..9b3a9d1 100644 --- a/src/grid_world_base.jl +++ b/src/grid_world_base.jl @@ -113,6 +113,15 @@ ind_map((i,j), (m, n), ::Right) = (j, n-i+1) ind_map((i,j), (m, n), ::Up) = (m-i+1, n-j+1) ind_map((i,j), (m, n), ::Down) = (i,j) +""" +Updates the agent view + +Args: + v::AbstractArray{Bool,3}: the current agent view as a 3D array with indices [type, x, y] + a::AbstractArray{Bool,3}: the current environment as a 3D array with indices [type, x, y] + p::CartesianIndex: location of the agent + dir::LRUD: direction the agent is looking +""" function get_agent_view!(v::AbstractArray{Bool,3}, a::AbstractArray{Bool,3}, p::CartesianIndex, dir::LRUD) view_size = (size(v, 2), size(v, 3)) grid_size = (size(a,2),size(a,3)) From f2f5c11a7c4c849126533894ebeec72a49182d7e Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Mon, 19 Oct 2020 14:37:29 -0400 Subject: [PATCH 27/28] Added w to arguments of get_agent_view and simplified --- src/abstract_grid_world.jl | 2 -- src/grid_world_base.jl | 23 ++++++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/abstract_grid_world.jl b/src/abstract_grid_world.jl index e022817..fe4d365 100644 --- a/src/abstract_grid_world.jl +++ b/src/abstract_grid_world.jl @@ -32,5 +32,3 @@ get_actions(w::AbstractGridWorld) = (MOVE_FORWARD, TURN_LEFT, TURN_RIGHT) get_agent_view_inds(w::AbstractGridWorld, s=(7,7)) = get_agent_view_inds(get_agent_pos(w).I, s, get_agent_dir(w)) -get_agent_view!(v::BitArray{3}, w::AbstractGridWorld) = get_agent_view!(v, convert(GridWorldBase, w), get_agent_pos(w), get_agent_dir(w)) - diff --git a/src/grid_world_base.jl b/src/grid_world_base.jl index 9b3a9d1..3159181 100644 --- a/src/grid_world_base.jl +++ b/src/grid_world_base.jl @@ -122,16 +122,25 @@ Args: p::CartesianIndex: location of the agent dir::LRUD: direction the agent is looking """ -function get_agent_view!(v::AbstractArray{Bool,3}, a::AbstractArray{Bool,3}, p::CartesianIndex, dir::LRUD) +function get_agent_view!(v::AbstractArray{Bool,3}, w::AbstractGridWorld; perspective::Bool=true) + a = convert(GridWorldBase, w) + p = get_agent_pos(w) + dir = get_agent_dir(w) + view_size = (size(v, 2), size(v, 3)) grid_size = (size(a,2),size(a,3)) - inds = get_agent_view_inds(p.I, view_size, dir) - valid_inds = CartesianIndices(grid_size) - for ind in CartesianIndices(inds) - if inds[ind] ∈ valid_inds - v[:, ind_map(ind.I, view_size, dir)...] .= a[:, inds[ind]] + inds = get_agent_view_inds(p.I, view_size, dir) # indices of the visible points + valid_inds = CartesianIndices(grid_size) # CartesianIndices representing the whole environment + + if perspective + + else + for ind in CartesianIndices(inds) # for every index in view... + if inds[ind] ∈ valid_inds # if it's within the environment... + # set its corresponding value in the view to the value in the environment + v[:, ind_map(ind.I, view_size, dir)...] .= a[:, inds[ind]] + end end end - v end From e71ea87c6868dec6ab4df09a056576904d226382 Mon Sep 17 00:00:00 2001 From: landrumb <36489943+landrumb@users.noreply.github.com> Date: Mon, 19 Oct 2020 16:22:08 -0400 Subject: [PATCH 28/28] implemented occlusion to get_agent_view --- src/grid_world_base.jl | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/grid_world_base.jl b/src/grid_world_base.jl index 3159181..0bab9a2 100644 --- a/src/grid_world_base.jl +++ b/src/grid_world_base.jl @@ -99,6 +99,15 @@ function (s::Shadow)(v::CartesianIndices) f.(polar) end +function shadowmap(m::Matrix{Bool}) + indices = CartesianIndices(((-1*size(m)[1]÷2):(size(m)[1]÷2), 0:(size(m)[2]-1))) + shadows = Shadow.(indices[m]) + output = fill(false, size(a)) + for s in shadows + output |= s(indices) + end + output +end ##### # get_agent_view ##### @@ -133,7 +142,20 @@ function get_agent_view!(v::AbstractArray{Bool,3}, w::AbstractGridWorld; perspec valid_inds = CartesianIndices(grid_size) # CartesianIndices representing the whole environment if perspective - + m = convert(Matrix{Bool}, copy(v)) + shadows = [] + for ind in CartesianIndices(inds) # for every index in view... + if inds[ind] ∈ valid_inds # if it's within the environment... + o = findfirst(w[:, inds[ind]]) # first object at the index + m[ind_map(ind.I, view_size, dir)...] .= isnothing(o) ? false : isopaque(w.objects[o]) <: Opaque + end + end + shadows = .!(shadowmap(m)) + for ind in CartesianIndices(inds) + if inds[ind] ∈ valid_inds && shadows[ind_map(ind.I, view_size, dir)...] + v[:, ind_map(ind.I, view_size, dir)...] .= a[:, inds[ind]] + end + end else for ind in CartesianIndices(inds) # for every index in view... if inds[ind] ∈ valid_inds # if it's within the environment...