Is Kithgaard Mastery possible to complete in the clojure language without the ability to cast to strings?


#1

Posting here first before making a github issue, but as I play through the game again in Clojurescript, when I get to the end of the Kithgaard Dungeon realm I wanted to play the “skip” level as well, Kithgaard Mastery, but am unable to complete it due to lacking a cast functionality in clojurescript.

The my code is at the bottom of this post, but the pertinent parts are:
;; Count how many gems you pick up, and then say the current count when near a fireball trap to disable it.

and

(.say this gems) ;which fails

I am no clojure expert, but I believe clojure requires explicit casting to cast to a string. Since gems is an integer, that expression fails. But there is no cast functionality in any of the equipment received in Kithgaard Mastery.

Is there just something else I’m missing?

;; Count how many gems you pick up, and then say the current count when near a fireball trap to disable it.
;; The raven at the start will give you a password. Say the password near a door to open it.
;; Kill ogres when you get near them.
;; You can use a loop to repeat all of the instructions as needed.
;; If you beat this level, you can skip to the Forest World!
(if (not gems) (def gems 0))
(.moveRight this)
(dotimes [n 2] (.moveUp this))
(dotimes [n 2] (def enemy (.findNearestEnemy this)) (if enemy (.attack this enemy)))
(.moveLeft this)
(dotimes [n 2] (.moveUp this))
(dotimes [n 2] (.moveRight this))
(.moveUp this)
(inc gems)
(.moveDown this)
(.moveRight this)
(dotimes [n 2] (.moveDown this))
(.say this gems)


#2

Generally you can use all language-concepts the language has, at least with some care. For example Pythons list-comprehensions are never actually introduced, but can still be used.

Python list comprehension
melee = [e for e in self.findEnemies() if e.type == "munchkin" or e.type == "scout"]

No clojure-expert, but you might try this method:

(.say this (str gems))

I’ve taken it from here.

Please note that clojure is an experimental language and may or may not be stable in later levels.


#3

It’s awesome that you’re giving Clojure a shot! It’s without a doubt my favorite language and can certainly help you to become a better programmer, even in other languages.

JFBM is correct regarding using str to cerce a number into a string. Unfortunately (inc gems) won’t actually mutate the gems var, though. Usually in Clojure mutation is something you try your best to avoid unless absolutely necessary. In this circumstance it seems reasonable enough, though.

You can use set! to mutate a var:

(set! gems (inc gems))

Note that if you were using actual Clojure outside of CodeCombat you’d have to declare the var as dynamic in order to rebind it. It is also a common idiom to surround the name with asterisks as a reminder of the var’s mutability. They’re often referred to as earmuffs:

(def ^:dynamic *gems* 0)

Again, it’s not required on CodeCombat and will probably throw an error as metadata isn’t supported yet. I’d still recommend using the earmuffs though.


#4

Yeah, (str gems) was something I thought of, but it’s simply not available to the character even by the end of Kithgard. Was one of the first things that I tried.

@Driphter good point about the immutability of ints, I haven’t really hit that wall yet, but it’s good to know that I need to adapt some C-like habits.

Anyway, (str whatever) is unavailable, though perhaps it should be a functionality added along with (.say) in the game system.


#5

This issue is now tracked here:

Please use GitHub to add any information I might have missed or conveyed incorrectly.
Thanks for your help in making CodeCombat a better game.


#6

For future reference for others, the cause was that the gems variable was wholly undefined, just quirkiness along the way prevented prior instructions in clojure from erroring around that fact.