Exercise help: Julia/Role Playing Game

First of all thanks for this great resource - for poor guys like me willing to learn. Also, apologies if this might not the right place but it’s the only post I found related to this Julia exercise.
I am a bit puzzled by some tests failing and the corresponding output. I tried to reproduce all possible cases offline and all looks good (including considering the case a name has already been incremented to avoid adding “the Great” again if’s already there.
Might well be something I am not considering or not doing right but I thought maybe not an raising this might improve this already amazing resource.
Thanks in advance for any help!

Welcome! And you’re very welcome.

Please create new threads for new questions :slight_smile:

Could you share your code, a specific test that is failing and the specific test output? Please use a codeblock and not a screenshot.

Did you run the tests following the testing instructions ?

This is quite a new exercise, so we are keen to understand any problems. Please help us by providing more detail.

So far, 47 people have completed the exercise: a low number by Exercism standards, but enough to reassure us that the tests are basically working. Maybe we could improve the instructions or hints (did you look at the hints?).

cc @depial

Sorry, for “offline” I meant working in parallel on VSCode/Jupiter on my laptop, trying myself all possible inputs. When I say some tests fail I am referring to the online editor. I haven’t installed the CLI locally and downloaded anything.

If you’re not running the tests, it’s really, really hard to know if your code is doing anything close to what the exercise requires your code to do :slight_smile: What you’re checking and what the tests check could be very different.

Sorry, I don’t even know how to use the forum (quote, etc…). Too many things to learn :slight_smile:
Below is the code and down below one of the failed tests.

Code

StringOrMissing = Union{String, Missing} # type union definition
IntOrNothing = Union{Int64, Nothing} # type union definition

@kwdef mutable struct Player
name::StringOrMissing = missing
level::Int64 = 0
health::Int64 = 100
mana::IntOrNothing = nothing
end

function introduce(player::Player)
return (ismissing(player.name) ? “Mighty Magician” : player.name)
end

function increment(mana::IntOrNothing)
return (isnothing(mana) ? 50 : mana + 100)
end

function increment(name::StringOrMissing)
return (ismissing(name) ? “The Great” : replace(name," the Great" => “”) * " the Great")
end

function title(player::Player)
return (player.level ≥ 42 ? increment(player.name) : player.name)
end

function revive(player::Player)
return (player.health ≤ 0 ? Player(player.name, player.level, 100,increment(player.mana)) : player)
end

Failed test

There’s a “preformated text” icon in the text format bar. You can use that to make a codeblock.

You do this around your code and it becomes readable:

```
type or paste code here
```

Yeah, that’s was my thought as well. Thanks for your time anyway.
Thing is (I am using the online editor) on the previous encounters exercise I too managed to get it to pass but I had to “cheat” if you like (code below).
The first ‘cheat’ was to go around the fact that other struct entities other than “Pets” did not have a “name” field. That is kind of okay but I don’t think that was mentioned in the instructions.
The second ‘cheat’ really is a reverse-engineered teak to the failed-test output.

Code of encounters exercise

# Define an abstract type Pet
abstract type Pet end
# Define concrete types Dog and Cat
struct Cat <: Pet
    name::String
end
struct Dog <: Pet
    name::String
end
"""struct Car
    name::String
end"""

# Define a name() function

name(p::Pet) = p.name

# Define multiple methods for meets(a, b)
# Only the first one is stubbed

meets(a::Dog, b::Dog) = "sniffs"
meets(a::Dog, b::Cat) = "chases"
meets(a::Cat, b::Dog) = "hisses"
meets(a::Cat, b::Cat) = "slinks"

# Implement the encounter(a, b) function
#@show Car
#encounter(a, b) = "$(getfield(a, 1)) meets $(getfield(b, 1)) and $(meets(a,b))."
function encounter(a, b)
    name_a = length(fieldnames(typeof(a))) > 0 ? getfield(a,1) : string(a)
    name_a = replace(name_a,"ExercismTestReports." =>"","(" =>"",")" => "")
    name_b = length(fieldnames(typeof(b))) > 0 ? getfield(b,1) : string(b)
    name_b = replace(name_b,"ExercismTestReports." =>"","(" =>"",")" => "")
    return "$(name_a) meets $(name_b) and $(meets(a,b))."
end
# Define three fallback methods for meets(a, b)
# Stubs are not provided for these, but look at the hints if necessary

meets(a::Cat, b::Pet) = "is cautious"
meets(a::Dog, b::Pet) = "is cautious"
meets(a::Pet, b::Dog) = "is cautious"
meets(a::Pet, b::Cat) = "is cautious"
meets(a::Pet, b) = "runs away"


meets(a, b) = "nothing happens"

You might want to edit your code and add those ``` to make your code readable :)

1 Like
# ROLE-PLAYING-GAME

StringOrMissing = Union{String, Missing}    # type union definition
IntOrNothing = Union{Int64, Nothing}    # type union definition

@kwdef mutable struct Player
    name::StringOrMissing = missing
    level::Int64 = 0
    health::Int64 = 100
    mana::IntOrNothing = nothing
end

function introduce(player::Player)
    return (ismissing(player.name) ? "Mighty Magician" : player.name)
end

function increment(mana::IntOrNothing)
    return (isnothing(mana) ? 50 : mana + 100)   
end

function increment(name::StringOrMissing)
    return (ismissing(name) ? "The Great" : replace(name," the Great" => "") * " the Great")
end

function title(player::Player)
    return (player.level ≥ 42 ? increment(player.name) : player.name) 
end

function revive(player::Player)
    return (player.health ≤ 0 ? Player(player.name, player.level, 100,increment(player.mana)) : player)
end

I did some more testing and would like to share. Hopefully with some clarity this time around…

First the code (again). Note there are two commented “@show player” in both the title() and revive() function.
I run the code twice, each time uncommenting one to get the input that is being used for the tests.

StringOrMissing = Union{String, Missing}    # type union definition
IntOrNothing = Union{Int64, Nothing}    # type union definition

@kwdef mutable struct Player
    name::StringOrMissing = missing
    level::Int64 = 0
    health::Int64 = 100
    mana::IntOrNothing = nothing
end

function introduce(player::Player)
    return (ismissing(player.name) ? "Mighty Magician" : player.name)
end

function increment(mana::IntOrNothing)
    return (isnothing(mana) ? 50 : mana + 100)   
end

function increment(name::StringOrMissing)
    return (ismissing(name) ? "The Great" : replace(name," the Great" => "") * " the Great")
end

function title(player::Player)
    #@show player
    return (player.level ≥ 42 ? increment(player.name) : player.name) 
end

function revive(player::Player)
    #@show player
    return (player.health ≤ 0 ? Player(player.name, player.level, 100,increment(player.mana)) : player)
end

Running first time with uncommented show in the title() function I get the following two title function failures:

Code Run

@test name == namedplayer.name == "Genie the Great"

Test Failure

Test Failed at ./runtests.jl:70 Expression: name == namedplayer.name == "Genie the Great" Evaluated: "Genie the Great" == "Genie" == "Genie the Great"

Code Run

@test name == unnamedplayer.name == "The Great"

Test Error

TypeError: non-boolean (Missing) used in boolean context Stacktrace: [1] eval_test(evaluated::Expr, quoted::Expr, source::LineNumberNode, negate::Bool)

Note the output, i.e. the “input”:

player = ExercismTestReports.Player(missing, 0, 100, nothing)
player = ExercismTestReports.Player("Willard", 21, 100, nothing)
player = ExercismTestReports.Player("Genie", 42, 50, nothing)
player = ExercismTestReports.Player(missing, 42, 100, nothing)

Running a second time, with show commented our in title() and uncommented in revive(), I get 4 revive function failures (same as before) and the corresponding output/input (2 failures shown only):

Code Run

@test player1.health == 100

Test Failure

Test Failed at ./runtests.jl:84 Expression: player1.health == 100 Evaluated: 0 == 100

Code Run

@test player1.mana == 50

Test Failure

Test Failed at ./runtests.jl:85 Expression: player1.mana == 50 Evaluated: nothing == 50

Note the output (i.e. input) in this case:

player = ExercismTestReports.Player(missing, 42, 0, nothing)
player = ExercismTestReports.Player(missing, 17, 0, 78)
player = ExercismTestReports.Player(missing, 5, 1, nothing)

Now, I have used these two outputs as input to test the same code (not shown below for clarity) on my laptop - using the Jupyter extension in VScode.
It seems to me that everything checks out and the results meet the requirements indicated in the instructions. Or, am I missing something?

#testing the title() function

players = [Player(missing, 0, 100, nothing)]
push!(players,Player("Willard", 21, 100, nothing))
push!(players,Player("Genie", 42, 50, nothing))
push!(players,Player(missing, 42, 100, nothing))

for player ∈ players
    println("player = $player -> title(player) = $(title(player))")
end

Results:

player = Player(missing, 0, 100, nothing) -> title(player) = missing
player = Player("Willard", 21, 100, nothing) -> title(player) = Willard
player = Player("Genie", 42, 50, nothing) -> title(player) = Genie the Great
player = Player(missing, 42, 100, nothing) -> title(player) = The Great

And

#testing the revive() function

players = [Player(missing, 42, 0, nothing)]
push!(players,Player(missing, 17, 0, 78))
push!(players,Player(missing, 5, 1, nothing))

for player ∈ players
    println("player = $player -> revive(player) = $(revive(player))")
end

Results:

player = Player(missing, 42, 0, nothing) -> revive(player) = Player(missing, 42, 100, 50)
player = Player(missing, 17, 0, 78) -> revive(player) = Player(missing, 17, 100, 178)
player = Player(missing, 5, 1, nothing) -> revive(player) = Player(missing, 5, 1, nothing)

Sorry for being a bit late to the game! It says this topic has been solved, but the marked “solution” doesn’t appear to be related to the exercise, so I’ll respond to adrm69’s last comment here. Feel free to ignore if the issue has indeed been solved.

@adrm69 Please try the following tests with your code:

player = Player(name="Svengali", level=42, health=36, mana=54)
title(player)

And look at the output. Now check:

player.name

These should match.

If you figure out the problem with this task, the other one you are having issues with should be solvable in the same way. :slight_smile:

Edit: Thank you for bringing this to our attention! We’ve updated the exercise to be clearer.

1 Like

Thanks depial!

That additional “!” in the instructions made all the difference, though the mutable struct definition should have rung a (!) bell !!! :rofl:
Again, thanks to all for your time and effort! :clap:

Just for clarity, for other beginner folks like myself reading this post, your example above should be modified accordingly

player = Player(name="Svengali", level=42, health=36, mana=54)
title!(player)
1 Like

No problem!

To prevent any confusion to future readers, I thought I’d clarify that anyone starting the exercise after this post will see the title!() and revive!() functions in the instructions and stub.

However, these used to be title() and revive() before @adrm69 brought this to our attention and we modified the exercise, hence their use throughout this thread.