RDM 9 consisted of three problems, with Easy being conceptually separate, while Medium and Hard were connected. In the Easy problem, the task was to write a web app with calculator functionality - but there’s a catch: the calculator was supposed to work with English rather than number symbols. The Medium and Hard problems focused on writing a very simple text adventure game where the player must find a treasure in a dungeon.
There’s basically two approaches here. You can look for a suitable library to convert between English and number representation, or you can write your own simple algo to do the conversion. The number bounds are reasonably small, so you won’t need to deal with very large numbers.
A very minimal solution approach could be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<head>
<title>RDM 7 - Hard</title>
<script type="text/javascript" src="/static/numberToWords.min.js"></script>
<script>
var table = {
"plus" : "+",
"minus": "-",
"times": "*",
"one": "1",
"two": "2",
"three": "3",
"four": "4",
"five": "5",
"six": "6",
"seven": "7",
"eight": "8",
"nine": "9",
"ten": "10"
}
function createExpression(st){
Object.keys(table).forEach((key) => st = st.replaceAll(key,table[key]));
return st;
}
function calculate() {
var content = document.getElementById("query").value;
try {
Object.keys(table).forEach((key) => content = content.replaceAll(key,table[key]));
document.getElementById("result").textContent = numberToWords.toWords(eval(content));
} catch (e) {
document.getElementById("result").textContent = "Invalid expression.";
}
}
</script>
</head>
Remember that this is a competition problem, and that you should be very careful with functions like eval() in any real life usage!
In the medium problem, you’re asked to develop a back-end API to support a very simple text adventure game. To achieve this, you must implement the game logic within your back-end, and provide endpoints to manipulate the game state.
The map for the Medium challenge game is as follows:
1 2 3 4 5 6 7
# # # # # # # #.....# #.# # #.# #.#G #.# #.#.#.# #.#...# # @ # # # # #
The back-end including both Medium and Hard requirements could be something similar to this file. As the specification does not ask for handling multiple sessions, it is possible to just use global state to implement the game logic. In real-life situations, when implementing a game or another app, you should be careful with global state, and consider your use case requirements for session handling. In this case, only one player is supported for the app at a time, and an approach like this could be useful when writing the first iteration of an app - once the app logic works as required, the next step should then be to refactor to support more features.
In the Hard challenge, the task is to provide a minimal web site front-end to the text adventure, with some additional game features. The map is different and slightly larger, and there is the new game mechanic of traps and player HP (hit points). It was possible to utilize the back-end created in the Medium challenge for the Hard problem, with suitable modifications to account for the new features.
The map in the Hard problem is pictured below:
1 2 3 4 5 6 7 8 9 10
# # # # # # # # # # #.....# # # # #.# # #x # #.# #.#G #.# #x # #.#.#....# #x..#x # #x # # # # # #.# # # # # #.......# #.x #.# # #x # # # # # @ # # # # #
The front-end code for this challenge could be similar to the following:
1 2 3 4 5 6 7 8 9 10 11 12 13
<body> <div id="message"></div> <div id="controls"> <br> <input type="button" id="left" onclick="turnLeft()" value="Turn left"></input> <input type="button" id="forward" onclick="goForward()" value="Move forward"></input> <input type="button" id="right" onclick="turnRight()" value="Turn right"></input> <br> <input type="button" id="right" onclick="startGame()" value="Start a new game"></input> <br> </div> <div id="status"></div> </body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
async function turnLeft() {
const data = await fetch("api/playHard", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify({
'move': 'left'
})
})
.then(res => res.json())
$("#message")
.text(data['Message']);
$("#status")
.text(data['Hitpoints'] + " HP");
};
async function goForward() {
const data = await fetch("api/playHard", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify({
'move': 'forward'
})
})
.then(res => res.json())
$("#message")
.text(data['Message']);
$("#status")
.text(data['Hitpoints'] + " HP");
};
async function turnRight() {
const data = await fetch("api/playHard", {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify({
'move': 'right'
})
})
.then(res => res.json())
$("#message")
.text(data['Message']);
$("#status")
.text(data['Hitpoints'] + " HP");
};
async function startGame() {
const data = await fetch("api/startHard")
.then(res => res.json())
$("#message")
.text(data['Message']);
$("#status")
.text(data['Hitpoints'] + " HP");
};