diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-001.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-001.md
new file mode 100644
index 00000000000..737056e9343
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-001.md
@@ -0,0 +1,33 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9de
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+Welcome to the dashboard project! You will be using the JavaScript data visualization library, D3, to build a visualization of your social media followers. It will consist of a line graph, a pie chart, and a legend.
+
+First, you need to create the HTML file. Start by adding the `` declaration at the top of the file to tell the browser what type of document it's reading.
+
+# --hints--
+
+test-text
+
+```js
+assert(//gi.test(code));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+```
+
+# --solutions--
+
+```html
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-002.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-002.md
new file mode 100644
index 00000000000..e69a56a6c39
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-002.md
@@ -0,0 +1,43 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9df
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+Next, add opening and closing `html`, `head` and `body` tags below the doctype. Be sure to nest them properly.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /\s*\s*
\s*<\/head\s*>\s*\s*<\/body\s*>\s*<\/html\s*>/gi.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-003.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-003.md
new file mode 100644
index 00000000000..4060dac9f7c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-003.md
@@ -0,0 +1,51 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9e0
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+In the head, add a `title` of `D3 Dashboard`.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /\s*D3 Dashboard<\/title\s*>\s*<\/head\s*>/g.test(code)
+);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+# --solutions--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-004.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-004.md
new file mode 100644
index 00000000000..92d0e9e6672
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-004.md
@@ -0,0 +1,55 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9e1
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+Below the title, link to your external stylesheet by adding a `link` element with a `rel` attribute of `stylesheet` and an `href` attribute of `./dashboard.css`. Remember that link elements do not need a closing tag. You will be adding some styles to this file shortly.
+
+# --hints--
+
+test-text
+
+```js
+const link = code.match(/]>/gi)[0];
+assert(
+ /rel\s*=\s*('|")\s*stylesheet\s*\1/gi.test(link) &&
+ /href\s*=\s*('|")\s*(.\/)?dashboard\.css\s*\1/gi.test(link)
+);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+# --solutions--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-005.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-005.md
new file mode 100644
index 00000000000..126ee1afb77
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-005.md
@@ -0,0 +1,55 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9e2
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+Next, add a container for the dashboard. Put an empty `div` element in the body with class of `dashboard`. You will be appending all the dashboard elements to this div.
+
+# --hints--
+
+test-text
+
+```js
+assert($('div.dashboard').length === 1);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+
+```
+
+# --solutions--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-006.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-006.md
new file mode 100644
index 00000000000..8d2dc0f0fc2
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-006.md
@@ -0,0 +1,55 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9e3
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+You are now looking at the stylesheet that you linked to earlier. At the top of this file, target the `body` of the HTML document and give it a `background-color` of `#ccc`.
+
+# --hints--
+
+test-text
+
+```js
+const body = code.match(/body\s*{[\s\S]+?[^}]}/g)[0];
+assert(/background-color\s*:\s*#ccc\s*(;|})/gi.test(body));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+```
+
+# --solutions--
+
+```html
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-007.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-007.md
new file mode 100644
index 00000000000..9c9637a79da
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-007.md
@@ -0,0 +1,66 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9e4
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Next, target the `dashboard` class you created and give it a `width` of `980px` and a `height` of `500px`.
+
+# --hints--
+
+test-text
+
+```js
+const dashboard = $('.dashboard');
+assert(
+ dashboard.css('width') === '980px' && dashboard.css('height') === '500px'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+```
+
+# --solutions--
+
+```html
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-008.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-008.md
new file mode 100644
index 00000000000..f30f2278512
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-008.md
@@ -0,0 +1,73 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9e5
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Give the dashboard a `background-color` of `white` and a `box-shadow` of `5px 5px 5px 5px #888` to give it a little depth.
+
+# --hints--
+
+test-text
+
+```js
+const dashboard = $('.dashboard');
+assert(
+ dashboard.css('background-color') === 'rgb(255, 255, 255)' &&
+ dashboard.css('box-shadow') === 'rgb(136, 136, 136) 5px 5px 5px 5px'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+```
+
+# --solutions--
+
+```html
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-009.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-009.md
new file mode 100644
index 00000000000..a9e92dd79e5
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-009.md
@@ -0,0 +1,73 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9e6
+title: Step 9
+challengeType: 0
+dashedName: step-9
+---
+
+# --description--
+
+Now you can see your dashboard element. Center it by adding a `margin` of `auto` to it.
+
+# --hints--
+
+test-text
+
+```js
+const dashboard = code.match(/.dashboard\s*{[\s\S]+?[^}]}/g)[0];
+assert(/margin\s*:\s*auto\s*(;|})/g.test(dashboard));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+```
+
+# --solutions--
+
+```html
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-010.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-010.md
new file mode 100644
index 00000000000..a5ebf98f5a0
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-010.md
@@ -0,0 +1,75 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9e7
+title: Step 10
+challengeType: 0
+dashedName: step-10
+---
+
+# --description--
+
+Give the container some space by adding a `padding` of `100px 10px` to the `body` element.
+
+# --hints--
+
+test-text
+
+```js
+const body = code.match(/body\s*{[\s\S]+?[^}]}/g)[0];
+assert(/padding\s*:\s*100px\s*10px\s*(;|})/g.test(body));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+```
+
+# --solutions--
+
+```html
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-011.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-011.md
new file mode 100644
index 00000000000..e852c01758e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-011.md
@@ -0,0 +1,81 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9e8
+title: Step 11
+challengeType: 0
+dashedName: step-11
+---
+
+# --description--
+
+Later on, you will be adding more elements to the dashboard container. Set the `display` to `flex` and the `align-items` to `center` so those items will be vertically centered.
+
+# --hints--
+
+test-text
+
+```js
+const dashboard = $('.dashboard');
+assert(
+ dashboard.css('display') === 'flex' &&
+ dashboard.css('align-items') === 'center'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+```
+
+# --solutions--
+
+```html
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-012.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-012.md
new file mode 100644
index 00000000000..c087db365e8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-012.md
@@ -0,0 +1,79 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9e9
+title: Step 12
+challengeType: 0
+dashedName: step-12
+---
+
+# --description--
+
+Back in the HTML file, add a `script` tag at the bottom of the head element and give it a `src` attribute of `./d3-5.9.2.min.js`. Don't forget the closing tag. This will add the D3 library to your project from a downloaded copy.
+
+# --hints--
+
+test-text
+
+```js
+const script = code.match(/
+
+
+
+
+
+
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-013.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-013.md
new file mode 100644
index 00000000000..1900674079c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-013.md
@@ -0,0 +1,96 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9ea
+title: Step 13
+challengeType: 0
+dashedName: step-13
+---
+
+# --description--
+
+Add another `script` below the one you just added. Give it a `src` attribute of `./data.js`.
+
+This adds a `data` variable to your project that contains your number of social media followers, it is an array of objects. Each object has the year and your followers for three different platforms. You will see what it looks like shortly.
+
+# --hints--
+
+test-text
+
+```js
+const script = code.match(/
+```
+
+## --seed-contents--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+
+
+
+```
+
+# --solutions--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+
+
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-014.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-014.md
new file mode 100644
index 00000000000..934305ffeb0
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-014.md
@@ -0,0 +1,95 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9eb
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+Add a third script just before the closing body tag. It will be the JavaScript file you will use to create the rest of the dashboard. Give the script a `src` of `./dashboard.js`.
+
+# --hints--
+
+test-text
+
+```js
+const script = code.match(/
+```
+
+## --seed-contents--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+
+
+
+
+```
+
+# --solutions--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+
+
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-015.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-015.md
new file mode 100644
index 00000000000..6972bb06c2a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-015.md
@@ -0,0 +1,103 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9ec
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+The script at the top is the `data.js` file you added. I have placed it here so you can see the data and recommend taking a look at it. The second script is the one you just added and where you will build the rest of the project.
+
+In the second script, create three `const` variables; `svgMargin` with a value of `70`, `svgWidth` with a value of `700`, and `svgHeight` equal to `500`. The first part of the dashboard will be a line graph. It will use these variables as its dimensions.
+
+The line graph will have the years from your data variable across the bottom, and a scale on the left to show the numbers of followers. Each platform will have a line going across the graph that shows how many followers you had for each year.
+
+# --hints--
+
+test-text
+
+```js
+assert(svgMargin === 70 && svgWidth === 700 && svgHeight === 500);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-016.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-016.md
new file mode 100644
index 00000000000..c518fc0fd82
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-016.md
@@ -0,0 +1,108 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9ed
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Add three more variables; `twitterColor` with a value of `#7cd9d1`, `tumblrColor` equal to `#f6dd71`, and `instagramColor` at `#fd9b98`. Make sure those Hex values are strings. These will be colors used to represent the different platforms throughout the project.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ twitterColor === '#7cd9d1' &&
+ tumblrColor === '#f6dd71' &&
+ instagramColor === '#fd9b98'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-017.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-017.md
new file mode 100644
index 00000000000..8537b5c634a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-017.md
@@ -0,0 +1,113 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9ee
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+When you added the D3 library earlier, it put an object named `d3` in your project with a bunch of functions. One of them is `select`; you can use dot notation to access this and the other functions from the object. Create a new variable named `lineGraph` and use `d3.select` to select the `.dashboard` element. Here's an example of something similar:
+
+```js
+const variableName = d3.select('.className')
+```
+
+# --hints--
+
+test-text
+
+```js
+assert(lineGraph._groups[0][0] === $('.dashboard')[0]);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-018.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-018.md
new file mode 100644
index 00000000000..e034d250e57
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-018.md
@@ -0,0 +1,117 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9ef
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+Your dashboard element is now "selected". D3 has a number of functions for working with a selection; one of them is `append`. It is used to add an element. Chain the `append` function to your selection and use it to add an `svg` element. Here's an example of how that might be done:
+
+```js
+const variableName = d3.select('selectedElement')
+ .append('elementToAdd')
+```
+
+# --hints--
+
+test-text
+
+```js
+assert(lineGraph._groups[0][0] === $('svg')[0]);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-019.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-019.md
new file mode 100644
index 00000000000..71a9b118ed1
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-019.md
@@ -0,0 +1,124 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9f0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+You can't see it, but there is now an `svg` element nested in your dashboard container. When you appended it, it became the "selection" for this area of code. Any functions you chain after it will be used on this selection.
+
+`attr` is a function to set attributes. You need to pass it the attribute you want to set, and the value you want to give it. Here's an example of how to chain `attr` to a selection:
+
+```js
+const variableName = d3.select('element')
+ .append('element')
+ .attr('attribute', 'value')
+```
+
+Chain an `attr` function to the selection that sets the `width` as the `svgWidth` variable you created earlier. When using a variable as a value, you do not need to put it in any kind of quotations.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg')[0].attributes.width.value === '700');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-020.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-020.md
new file mode 100644
index 00000000000..64d86709ab6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-020.md
@@ -0,0 +1,116 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9f1
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Chain another `attr` function that sets the `height` as the `svgHeight` variable you created.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg')[0].attributes.height.value === '500');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-021.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-021.md
new file mode 100644
index 00000000000..06bcb3f2432
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-021.md
@@ -0,0 +1,123 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9f2
+title: Step 21
+challengeType: 0
+dashedName: step-21
+---
+
+# --description--
+
+Your line graph needs some scales so it knows how to translate the data into visual distances. The first one is the scale for the y-axis. It will be to show the number of followers. D3 has many utilities for creating scales. You want to use it's `scaleLinear` method for this scale.
+
+Create a new `const` named `yScale`, and set it equal to `d3.scaleLinear()`.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ typeof yScale === 'function' && /yScale\s*=\s*d3\.scaleLinear/.test(code)
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-022.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-022.md
new file mode 100644
index 00000000000..20a021de05d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-022.md
@@ -0,0 +1,123 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9f3
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+D3 has a bunch of functions for working with scales as well. One of them is `domain`. It takes an array that is used to describe the highest and lowest values of the data for this scale. After a quick look at the data, the values of the "followers" go from about 0 to 5000. Chain the `domain` function to the `yScale` and pass it the array `[0, 5000]`.
+
+# --hints--
+
+test-text
+
+```js
+const domain = yScale.domain();
+assert(domain.length === 2 && domain[0] === 0 && domain[1] === 5000);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-023.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-023.md
new file mode 100644
index 00000000000..e7a769694bf
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-023.md
@@ -0,0 +1,129 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9f4
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+The `range` function describes how to map the domain values for display on the graph. For example, a value of 5000 followers can't use 5000 as it y-coordinate on the SVG or it would be off the graph. You need to tell the range where the top and bottom of the graph is so the scale can give appropriate values for the y-coordinate.
+
+Chain the `range` function below the `domain` and pass it an array with `svgHeight - svgMargin` and `svgMargin` as the values. That will translate to `[430, 70]`. This is where the top and bottom of the graph are. So a data point of 5000 followers will map to a value of 430 to use as its y-coordinate and 0 followers will use 70 as its y-coordinate. Any value in between will scale linearly.
+
+Your graph will have a margin around it for things like axes and labels. The actual line data will display on the inside of this margin area, which is why you use those values. This will become more clear as you progress through the project.
+
+# --hints--
+
+test-text
+
+```js
+const range = yScale.range();
+assert(range.length === 2 && range[0] === 430 && range[1] === 70);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-024.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-024.md
new file mode 100644
index 00000000000..bfb5cb47cf4
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-024.md
@@ -0,0 +1,129 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9f5
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Create a new `const` named `xScale`. Use it to create another linear scale like you did for the y-scale. This will be the horizontal or "x" axis.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ typeof xScale === 'function' && /xScale\s*=\s*d3\.scaleLinear/.test(code)
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-025.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-025.md
new file mode 100644
index 00000000000..0ad79254818
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-025.md
@@ -0,0 +1,131 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9f6
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+The `year` values of your data will be used for the x-scale. Chain the `domain` function to `xScale` and pass it an array with the first and last years of your data.
+
+# --hints--
+
+test-text
+
+```js
+const domain = xScale.domain();
+assert(domain.length === 2 && domain[0] === 2012 && domain[1] === 2020);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-026.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-026.md
new file mode 100644
index 00000000000..c2eda71b4f8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-026.md
@@ -0,0 +1,133 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9f7
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+The range for this scale will go from the left of your graph to the right, with 2012 on the left and 2020 on the right. Add the `range` function to the `xScale` and pass it an array with the values: `svgMargin` and `svgWidth - svgMargin`. This will translate to `[70, 630]`. So 2012 will use 70 as is x-coordinate and 2020 will use 630 as its x-coordinate.
+
+# --hints--
+
+test-text
+
+```js
+const range = xScale.range();
+assert(range.length === 2 && range[0] === 70 && range[1] === 630);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-027.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-027.md
new file mode 100644
index 00000000000..fadf8788314
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-027.md
@@ -0,0 +1,138 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9f8
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+The two scales you defined will be used to create the axes and lines. First is the y-axis, it will be a line with some labels on the left of the graph. Create a new `const` named `yAxis` and set it equal to `d3.axisLeft(yScale)`. This will use the information from the `yScale` variable to build the axis.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ typeof yAxis === 'function' &&
+ /yAxis\s*=\s*d3\.axisLeft\(\s*yScale\)/.test(code)
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-028.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-028.md
new file mode 100644
index 00000000000..3c6e36d9cc2
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-028.md
@@ -0,0 +1,142 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9f9
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Create a new `const` named `xAxis` and set the value equal to `d3.axisBottom(xScale)`. This will create another axis for the bottom of the graph using the information from `xScale`. Although the axes do not display yet, they have the information they need to display correctly.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ typeof xAxis === 'function' &&
+ /xAxis\s*=\s*d3\.axisBottom\(\s*xScale\)/.test(code)
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-029.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-029.md
new file mode 100644
index 00000000000..aae1810fbf7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-029.md
@@ -0,0 +1,143 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9fa
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+On a new line, append a new `g` element to your `lineGraph` variable. `lineGraph.append('g')` will do that for you. This will add a `g` to your SVG and be for displaying the y-axis. `g` is an SVG element that stands for "group".
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg')[0].children[0] === $('g')[0] && $('g').length === 1);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-030.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-030.md
new file mode 100644
index 00000000000..5a8d4514367
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-030.md
@@ -0,0 +1,147 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9fb
+title: Step 30
+challengeType: 0
+dashedName: step-30
+---
+
+# --description--
+
+`call` is another function to use with selections. Chain a `call` function to the selection and pass your `yAxis` variable to it. This will draw your y-axis on the SVG.
+
+# --hints--
+
+test-text
+
+```js
+assert($('.tick').length === 11 && /\.call\(\s*yAxis\s*\)/.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-031.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-031.md
new file mode 100644
index 00000000000..94721751a99
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-031.md
@@ -0,0 +1,151 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9fc
+title: Step 31
+challengeType: 0
+dashedName: step-31
+---
+
+# --description--
+
+After all that work, something is finally displayed on the graph. It's the y-axis and all the numbers are hidden on the left.
+
+Move the axis your `svgMargin` to the right by chaining an `attr` function to the selection. Use it to set the `transform` to `translate(${svgMargin}, 0)`. Use a template literal (backticks) to set the value so you can put your variable in there.
+
+# --hints--
+
+test-text
+
+```js
+assert($('g')[0].attributes.transform.nodeValue === 'translate(70, 0)');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-032.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-032.md
new file mode 100644
index 00000000000..1482a45c496
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-032.md
@@ -0,0 +1,150 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9fd
+title: Step 32
+challengeType: 0
+dashedName: step-32
+---
+
+# --description--
+
+`style` is a function similar to `attr`, but is more for manipulating CSS styles rather than element attributes. Add a `style` function to the selection that sets the `font` to `10px verdana`.
+
+# --hints--
+
+test-text
+
+```js
+assert($('g')[0].attributes.style.nodeValue === 'font: 10px verdana;');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-033.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-033.md
new file mode 100644
index 00000000000..838f00a1e26
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-033.md
@@ -0,0 +1,153 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9fe
+title: Step 33
+challengeType: 0
+dashedName: step-33
+---
+
+# --description--
+
+On a new line, append another `g` element to your `lineGraph` variable like you did before. This one will be for the x-axis.
+
+# --hints--
+
+test-text
+
+```js
+assert($('g').length === 13);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-034.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-034.md
new file mode 100644
index 00000000000..ffd84f411a9
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-034.md
@@ -0,0 +1,156 @@
+---
+id: 5d8a4cfbe6b6180ed9a1c9ff
+title: Step 34
+challengeType: 0
+dashedName: step-34
+---
+
+# --description--
+
+Use the `call` function to draw the x-axis onto the SVG like you did for the y-axis.
+
+# --hints--
+
+test-text
+
+```js
+assert($('g').length === 22);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-035.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-035.md
new file mode 100644
index 00000000000..e5afa9d8688
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-035.md
@@ -0,0 +1,158 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca00
+title: Step 35
+challengeType: 0
+dashedName: step-35
+---
+
+# --description--
+
+The axis has the right size and labels, but needs to be moved down. Use the `attr` function to set the `transform` like you did before. This time move it down your `svgHeight` minus the `svgMargin`.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg > g')[1].attributes.transform.nodeValue === 'translate(0, 430)');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-036.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-036.md
new file mode 100644
index 00000000000..61a26b75fff
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-036.md
@@ -0,0 +1,168 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca01
+title: Step 36
+challengeType: 0
+dashedName: step-36
+---
+
+# --description--
+
+The axis labels are `text` elements within the `g`, you can use the `selectAll` function to select them. Chain the `selectAll` function to select the `text` elements in this group. You can do that like this:
+
+```js
+.selectAll('element')
+```
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /\.attr\('transform', `translate\(0, \$\{svgHeight - svgMargin\}\)`\)\s*\.selectAll\s*\(\s*('|"|`)text\1\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-037.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-037.md
new file mode 100644
index 00000000000..194e3ad318c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-037.md
@@ -0,0 +1,168 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca02
+title: Step 37
+challengeType: 0
+dashedName: step-37
+---
+
+# --description--
+
+I want the text elements to be rotated slightly. Chain the `style` function to set the `transform` to `translate(-12px, 0) rotate(-50deg)`. This will put them at an angle.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('.tick > text').filter(
+ (node, index) =>
+ index.style.transform === 'translate(-12px) rotate(-50deg)' ||
+ index.style.transform === 'translate(-12px, 0px) rotate(-50deg)'
+ ).length === 9
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-038.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-038.md
new file mode 100644
index 00000000000..b17ce9013b1
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-038.md
@@ -0,0 +1,168 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca03
+title: Step 38
+challengeType: 0
+dashedName: step-38
+---
+
+# --description--
+
+Add another `style` function to set the `text-anchor` to `end`. This will change the spot that each text element rotates around to the `end` of the element so they will align better.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('.tick > text').filter(
+ (node, index) => index.style['text-anchor'] === 'end'
+ ).length === 9
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-039.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-039.md
new file mode 100644
index 00000000000..2025374c7a1
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-039.md
@@ -0,0 +1,173 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca04
+title: Step 39
+challengeType: 0
+dashedName: step-39
+---
+
+# --description--
+
+Add two more `style` functions; one to set the `cursor` to `pointer`, and another to set the `font` to `10px verdana`.
+
+You will add some hover effects later, so the pointer will make for a better experience.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('.tick > text').filter(
+ (node, index) =>
+ index.style.cursor === 'pointer' && index.style.font === '10px verdana'
+ ).length === 9
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-040.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-040.md
new file mode 100644
index 00000000000..52d9a027fd4
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-040.md
@@ -0,0 +1,178 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca05
+title: Step 40
+challengeType: 0
+dashedName: step-40
+---
+
+# --description--
+
+There are a number of D3 functions to work with how the "ticks" or your axis labels are displayed; one of them is `ticks`. Go back to where you defined the `yAxis` variable and chain a `ticks` function to it and pass it these two arguments: `6, '~s'`.
+
+The `6` will set the number of ticks used to 6, and the `~s` will make the labels display the number of thousands followed by a `k`. For example, `4000` will become `4k`.
+
+# --hints--
+
+test-text
+
+```js
+const ticks = $('.tick > text');
+assert(
+ ticks[0].innerHTML === '0k' &&
+ ticks[1].innerHTML === '1k' &&
+ ticks[2].innerHTML === '2k' &&
+ ticks[3].innerHTML === '3k' &&
+ ticks[4].innerHTML === '4k' &&
+ ticks[5].innerHTML === '5k'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-041.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-041.md
new file mode 100644
index 00000000000..82a3261d9b5
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-041.md
@@ -0,0 +1,171 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca06
+title: Step 41
+challengeType: 0
+dashedName: step-41
+---
+
+# --description--
+
+Go back to where you defined your `xAis` variable and chain the `tickFormat` function to it. Pass it `d3.format('')`. This will remove the commas in the year labels of the x-axis.
+
+# --hints--
+
+test-text
+
+```js
+const ticks = $('.tick > text');
+assert(ticks[6].innerHTML === '2012' && ticks[14].innerHTML === '2020');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-042.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-042.md
new file mode 100644
index 00000000000..aa8a37baf20
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-042.md
@@ -0,0 +1,178 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca07
+title: Step 42
+challengeType: 0
+dashedName: step-42
+---
+
+# --description--
+
+In the same spot, chain the `tickPadding` function to the `xAxis` and pass it `10`. This will add a little padding to the ticks so the labels are better aligned.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /\.tickFormat\(d3\.format\((''\)\)\s*\.tickPadding\s*\(\s*10\s*\))/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-043.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-043.md
new file mode 100644
index 00000000000..a91e12f41e6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-043.md
@@ -0,0 +1,178 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca08
+title: Step 43
+challengeType: 0
+dashedName: step-43
+---
+
+# --description--
+
+The axes and labels are looking good. Next, you will start to add some of the lines for the data. First is the line for the Twitter data. On a new line, create a new `const` named `twitterLine` and set it equal to `d3.line()`. `line` is a D3 function for creating a line.
+
+# --hints--
+
+test-text
+
+```js
+assert(/const\s*twitterLine\s*=\s*d3\s*\.\s*line\s*\(\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-044.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-044.md
new file mode 100644
index 00000000000..5a93e72d48f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-044.md
@@ -0,0 +1,192 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca09
+title: Step 44
+challengeType: 0
+dashedName: step-44
+---
+
+# --description--
+
+The line needs x and y values for each point of data. Chain `x` to the line and pass it a "d function". Here's how that will look:
+
+```js
+.x(d => d.year)
+```
+
+You will be passing your `data` array to this line function, where it will go through each item in the array(`d`) and create an x value based on the year(`d.year`).
+
+This is the first place you have seen a "d function". These are common in D3 and that is how I will refer to them throughout this project.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const twitterLine = d3\.line\(\)\s*\.x\s*\(\s*d\s*=>\s*d\.year\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-045.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-045.md
new file mode 100644
index 00000000000..e07ef7245ce
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-045.md
@@ -0,0 +1,183 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca0a
+title: Step 45
+challengeType: 0
+dashedName: step-45
+---
+
+# --description--
+
+Instead of simply using the year(`d.year`) for the x-coordinate, you need to pass each year to the `xScale` so it can set the appropriate coordinate based on your scale.
+
+In the "d function" you created, return `xScale(d.year)` instead of `d.year`.
+
+# --hints--
+
+test-text
+
+```js
+assert(/\.x\s*\(d\s*=>\s*xScale\s*\(\s*d\.year\s*\)\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-046.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-046.md
new file mode 100644
index 00000000000..9ba6b01ac8e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-046.md
@@ -0,0 +1,189 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca0b
+title: Step 46
+challengeType: 0
+dashedName: step-46
+---
+
+# --description--
+
+Chain the `y` function to the line and pass it a "d function" that returns your `yScale` with `d.followers.twitter` as its argument.
+
+This is similar to how you set the x values. It will use the values of your Twitter followers and your `yScale` to set the y coordinate for each item.
+
+These "d functions" use implicit returns. But if you add curly brackets and a return statement, you can put any JavaScript in there that you want. Including `console.log` statements that can be useful for debugging.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /\.y\s*\(\s*d\s*=>\s*yScale\s*\(\s*d\.followers.twitter\s*\)\s*\)/g.test(code)
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-047.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-047.md
new file mode 100644
index 00000000000..27b6eb3229d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-047.md
@@ -0,0 +1,189 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca0c
+title: Step 47
+challengeType: 0
+dashedName: step-47
+---
+
+# --description--
+
+The first line is created and ready to be displayed, which will take a couple steps. On a new line, `append` a `path` element to your `lineGraph` variable. This is similar to how you appended the `g` before.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('svg path').length === 3 &&
+ /lineGraph\.append\((`|'|")path\1\)/gi.test(code)
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-048.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-048.md
new file mode 100644
index 00000000000..0af7e8110d7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-048.md
@@ -0,0 +1,193 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca0d
+title: Step 48
+challengeType: 0
+dashedName: step-48
+---
+
+# --description--
+
+Tell the path what data to use. Add an `attr` function and set the `d` to `twitterLine(data)`. This will the build the path using the `twitterLine` function you created and your data variable.
+
+Note that the `d` in this case is a path attribute for drawing a line and is different from a "d function".
+
+After you have added your code, take a look at the data flow to help understand what is happening. You pass the data array to your `twitterLine` function where it sets the x and y values using your "d functions". The "d functions" go through each item in the array, passing part of the item to each scale to find the appropriate coordinates. When it's done, the value you are setting here is created and sent back. The result ends up being a confusing string of numbers and coordinates to tell the path how to be drawn.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg path')[2].getAttribute('d').length === 151);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-049.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-049.md
new file mode 100644
index 00000000000..880f7b5d0a6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-049.md
@@ -0,0 +1,199 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca0e
+title: Step 49
+challengeType: 0
+dashedName: step-49
+---
+
+# --description--
+
+Add three more `attr` functions to the path; one to set the `stroke` to your `twitterColor` variable, another to set the `stroke-width` to `3`, and a third to set the `fill` to `transparent`.
+
+# --hints--
+
+test-text
+
+```js
+const twitterPath = $('svg path')[2];
+assert(
+ twitterPath.getAttribute('stroke') === '#7cd9d1' &&
+ twitterPath.getAttribute('stroke-width') == '3' &&
+ twitterPath.getAttribute('fill') === 'transparent'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-050.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-050.md
new file mode 100644
index 00000000000..21584d84adf
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-050.md
@@ -0,0 +1,198 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca0f
+title: Step 50
+challengeType: 0
+dashedName: step-50
+---
+
+# --description--
+
+On a new line, create a new `const` named `tumblrLine` and set it equal to `d3.line()`.
+
+# --hints--
+
+test-text
+
+```js
+assert(/const\s*tumblrLine\s*=\s*d3\s*\.\s*line\s*\(\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-051.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-051.md
new file mode 100644
index 00000000000..3c1c0750188
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-051.md
@@ -0,0 +1,204 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca10
+title: Step 51
+challengeType: 0
+dashedName: step-51
+---
+
+# --description--
+
+Set the `x` values for `tumblrLine` using another "d function". Use your `xScale` and the `d.year` to calculate their values just like you did for the Twitter line.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const tumblrLine = d3\.line\(\)\s*\.x\s*\(\s*d\s*=>\s*xScale\s*\(\s*d\.year\s*\)\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-052.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-052.md
new file mode 100644
index 00000000000..74a4638e890
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-052.md
@@ -0,0 +1,207 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca11
+title: Step 52
+challengeType: 0
+dashedName: step-52
+---
+
+# --description--
+
+Set the `y` values for `tumblrLine` using a "d function" again. Use your `yScale` and `d.followers.tumblr` to calculate their values just like you did for the Twitter line.
+
+The x values for each line will be the same, but the y values will use the data from the different platforms.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /\.y\s*\(\s*d\s*=>\s*yScale\s*\(\s*d\.followers.tumblr\s*\)\s*\)/g.test(code)
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-053.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-053.md
new file mode 100644
index 00000000000..746e1ab4b1a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-053.md
@@ -0,0 +1,209 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca12
+title: Step 53
+challengeType: 0
+dashedName: step-53
+---
+
+# --description--
+
+On a new line, `append` a `path` element to the `lineGraph` variable. This one will be for displaying the `tumblrLine`.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('svg path').length === 4 &&
+ code.match(/lineGraph\.append\((`|'|")path\1\)/gi).length === 2
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-054.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-054.md
new file mode 100644
index 00000000000..695da3fee70
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-054.md
@@ -0,0 +1,209 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca13
+title: Step 54
+challengeType: 0
+dashedName: step-54
+---
+
+# --description--
+
+Tell the new path how to be drawn by setting the `d` attribute to `tumblrLine(data)` using the `attr` function.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg path')[3].getAttribute('d').length === 115);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-055.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-055.md
new file mode 100644
index 00000000000..a200a166f95
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-055.md
@@ -0,0 +1,218 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca14
+title: Step 55
+challengeType: 0
+dashedName: step-55
+---
+
+# --description--
+
+Add three `attr` functions to the selection; one to set the `stroke` to your `tumblrColor` variable, another to set the `stroke-width` to `3`, and a third to set the `fill` to `transparent`.
+
+# --hints--
+
+test-text
+
+```js
+const tumblrPath = $('svg path')[3];
+assert(
+ tumblrPath.getAttribute('stroke') === '#f6dd71' &&
+ tumblrPath.getAttribute('stroke-width') == '3' &&
+ tumblrPath.getAttribute('fill') === 'transparent'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-056.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-056.md
new file mode 100644
index 00000000000..c4f75859463
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-056.md
@@ -0,0 +1,218 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca15
+title: Step 56
+challengeType: 0
+dashedName: step-56
+---
+
+# --description--
+
+Two lines down, only one more to add for the Instagram followers. On a new line, create a new `const` named `instagramLine` and use the D3 `line` function to create another line like you did for the other two.
+
+# --hints--
+
+test-text
+
+```js
+assert(/const\s*instagramLine\s*=\s*d3\s*\.\s*line\s*\(\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-057.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-057.md
new file mode 100644
index 00000000000..59e2b7b22ca
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-057.md
@@ -0,0 +1,226 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca16
+title: Step 57
+challengeType: 0
+dashedName: step-57
+---
+
+# --description--
+
+Appropriately set the `x` values for `instagramLine` like you did for the other two lines.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const instagramLine = d3\.line\(\)\s*\.x\s*\(\s*d\s*=>\s*xScale\s*\(\s*d\.year\s*\)\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-058.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-058.md
new file mode 100644
index 00000000000..ad99613e2db
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-058.md
@@ -0,0 +1,229 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca17
+title: Step 58
+challengeType: 0
+dashedName: step-58
+---
+
+# --description--
+
+Appropriately set the `y` values for `instagramLine` like you did for the other two lines. Use the Instagram followers data this time.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /\.y\s*\(\s*d\s*=>\s*yScale\s*\(\s*d\.followers.instagram\s*\)\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-059.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-059.md
new file mode 100644
index 00000000000..fe46511da37
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-059.md
@@ -0,0 +1,231 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca18
+title: Step 59
+challengeType: 0
+dashedName: step-59
+---
+
+# --description--
+
+On a new line, `append` a new `path` for the Instagram line like you did for the other two lines.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('svg path').length === 5 &&
+ code.match(/lineGraph\.append\((`|'|")path\1\)/gi).length === 3
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-060.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-060.md
new file mode 100644
index 00000000000..5863f052f3d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-060.md
@@ -0,0 +1,230 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca19
+title: Step 60
+challengeType: 0
+dashedName: step-60
+---
+
+# --description--
+
+Use your `instagramLine` variable and your data to set the `d` attribute for this path like you did for the other two.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg path')[4].getAttribute('d').length === 171);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-061.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-061.md
new file mode 100644
index 00000000000..45e97e2ba69
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-061.md
@@ -0,0 +1,239 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca1a
+title: Step 61
+challengeType: 0
+dashedName: step-61
+---
+
+# --description--
+
+Set the `stroke`, `stroke-width`, and `fill` attributes to their appropriate values for this line. The `stroke-width` and `fill` are the same as the other two.
+
+# --hints--
+
+test-text
+
+```js
+const instagramPath = $('svg path')[4];
+assert(
+ instagramPath.getAttribute('stroke') === '#fd9b98' &&
+ instagramPath.getAttribute('stroke-width') == '3' &&
+ instagramPath.getAttribute('fill') === 'transparent'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-062.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-062.md
new file mode 100644
index 00000000000..82eef8d81e7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-062.md
@@ -0,0 +1,247 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca1b
+title: Step 62
+challengeType: 0
+dashedName: step-62
+---
+
+# --description--
+
+Okay, your graph is coming along. All the lines are drawn, but they look a little plain. The next series of code additions will add circles to each point on each line. First is the Twitter line. On a new line, use the `selectAll` function on your `lineGraph` variable and pass it the string `twitter-circles`. It will look like this:
+
+```js
+lineGraph.selectAll('twitter-circles')
+```
+
+`twitter-circles` don't exist and this selection will be an empty array, but it's needed. For now, you can just think of this string as a reference, similar to a variable name, so you know what elements you are working with.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /lineGraph\s*\.\s*selectAll\s*\((`|'|")\s*twitter-circles\1\s*\)/g.test(code)
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-063.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-063.md
new file mode 100644
index 00000000000..942bc905877
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-063.md
@@ -0,0 +1,246 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca1c
+title: Step 63
+challengeType: 0
+dashedName: step-63
+---
+
+# --description--
+
+Add the D3 `data` function to your selection and pass it the data array like this:
+
+```js
+.data(data)
+```
+
+# --hints--
+
+test-text
+
+```js
+assert(/\.data\s*\(\s*data\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-064.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-064.md
new file mode 100644
index 00000000000..db5343e098f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-064.md
@@ -0,0 +1,248 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca1d
+title: Step 64
+challengeType: 0
+dashedName: step-64
+---
+
+# --description--
+
+Next, chain the `enter()` function to the selection.
+
+The enter function identifies elements that need to be added when the data array is longer than the selection array. This is why you wanted the `selectAll` to be an empty array before.
+
+In this case, the `twitter-circles` selection has a length of 0, and the data array has a length of 9. So nine elements will be added when you use `append` in the next step.
+
+# --hints--
+
+test-text
+
+```js
+assert(/\.data\(data\)\s*\.enter\s*\(\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-065.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-065.md
new file mode 100644
index 00000000000..609632232b4
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-065.md
@@ -0,0 +1,246 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca1e
+title: Step 65
+challengeType: 0
+dashedName: step-65
+---
+
+# --description--
+
+Add the `append` function to the selection, and use it to add `circle` elements. This will add the nine `circle` elements for your Twitter circles. They will be invisible to start, but the elements are there.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg circle').length === 9);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-066.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-066.md
new file mode 100644
index 00000000000..d5291b996da
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-066.md
@@ -0,0 +1,250 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca1f
+title: Step 66
+challengeType: 0
+dashedName: step-66
+---
+
+# --description--
+
+Each circle needs a `cx` and `cy` attribute so it knows where to display on the SVG. These are similar to the x and y coordinates for the lines and will be calculated in the same way. The difference is that, for circles, the `cx` and `cy` are attributes, so you need to use the `attr` function.
+
+Use the `attr` function to set the `cx` to `d => xScale(d.year)`.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg circle')[0].getAttribute('cx') == '70');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-067.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-067.md
new file mode 100644
index 00000000000..f8b852ac2b8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-067.md
@@ -0,0 +1,252 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca20
+title: Step 67
+challengeType: 0
+dashedName: step-67
+---
+
+# --description--
+
+Next, set the `cy` attribute to `d => xScale(d.followers.twitter)`.
+
+As a reminder, this will pass each value of your Twitter followers to the `xScale` function where it will determine the y coordinate to use.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg circle')[0].getAttribute('cy') == '243.232');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-068.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-068.md
new file mode 100644
index 00000000000..ad9dfcf5dfc
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-068.md
@@ -0,0 +1,252 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca21
+title: Step 68
+challengeType: 0
+dashedName: step-68
+---
+
+# --description--
+
+Circles also need an `r` (radius) attribute so they know how big to be. Use the `attr` function to set the `r` to `6`.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg circle')[0].getAttribute('r') == '6');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-069.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-069.md
new file mode 100644
index 00000000000..9d2d9c5b0b0
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-069.md
@@ -0,0 +1,258 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca22
+title: Step 69
+challengeType: 0
+dashedName: step-69
+---
+
+# --description--
+
+The circles are now visible, but I don't like the color. Use the appropriate function to set the `fill` to `white` and the `stroke` to your `twitterColor` variable.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('svg circle')[0].getAttribute('fill') === 'white' &&
+ $('svg circle')[0].getAttribute('stroke') === '#7cd9d1'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-070.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-070.md
new file mode 100644
index 00000000000..e8beb17a75b
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-070.md
@@ -0,0 +1,258 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca23
+title: Step 70
+challengeType: 0
+dashedName: step-70
+---
+
+# --description--
+
+Use the `style` function to set the `cursor` to `pointer`. Like your year labels, this will be an indicator for a hover effect you will add later.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg circle')[0].style.cursor === 'pointer');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-071.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-071.md
new file mode 100644
index 00000000000..25b5c92d036
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-071.md
@@ -0,0 +1,263 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca24
+title: Step 71
+challengeType: 0
+dashedName: step-71
+---
+
+# --description--
+
+On a new line, use the `selectAll` function on your `lineGraph` variable again and pass it the string `tumblr-circles` this time. The next few steps will be for adding circles to the Tumblr line.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /lineGraph\s*\.\s*selectAll\s*\((`|'|")\s*tumblr-circles\1\s*\)/g.test(code)
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-072.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-072.md
new file mode 100644
index 00000000000..b5eee1874d9
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-072.md
@@ -0,0 +1,268 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca25
+title: Step 72
+challengeType: 0
+dashedName: step-72
+---
+
+# --description--
+
+Add the same `data`, `enter`, and `append` functions here that you added for the `twitter-circles`, passing in the same arguments. Make sure they are in the same order.
+
+Remember that this will take the difference in length between the `tumblr-circles` selection(0) and the data array(9) and append that many circle elements.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg circle').length === 18);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-073.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-073.md
new file mode 100644
index 00000000000..4d3a27e49d0
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-073.md
@@ -0,0 +1,274 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca26
+title: Step 73
+challengeType: 0
+dashedName: step-73
+---
+
+# --description--
+
+Set the `cx` and `cy` attributes for the Tumblr circles to their appropriate values.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('svg circle')[9].getAttribute('cx') == '70' &&
+ $('svg circle')[9].getAttribute('cy') == '401.128'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-074.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-074.md
new file mode 100644
index 00000000000..df1221f436d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-074.md
@@ -0,0 +1,280 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca27
+title: Step 74
+challengeType: 0
+dashedName: step-74
+---
+
+# --description--
+
+Use the `attr` function to set the `r` to `6`, the `fill` to `white`, and the `stroke` to your `tumblrColor` variable.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('svg circle')[9].getAttribute('r') == '6' &&
+ $('svg circle')[9].getAttribute('fill') === 'white' &&
+ $('svg circle')[9].getAttribute('stroke') === '#f6dd71'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-075.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-075.md
new file mode 100644
index 00000000000..53c158898b0
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-075.md
@@ -0,0 +1,280 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca28
+title: Step 75
+challengeType: 0
+dashedName: step-75
+---
+
+# --description--
+
+Set the `cursor` to `pointer` using the `style` function.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg circle')[9].style.cursor === 'pointer');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-076.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-076.md
new file mode 100644
index 00000000000..dfef7440d25
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-076.md
@@ -0,0 +1,287 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca29
+title: Step 76
+challengeType: 0
+dashedName: step-76
+---
+
+# --description--
+
+The circles have been added to two of the lines and look good, on to the last one. On a new line, create another empty selection like you did before. Use the string: `instagram-circles` this time.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /lineGraph\s*\.\s*selectAll\s*\((`|'|")\s*instagram-circles\1\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-077.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-077.md
new file mode 100644
index 00000000000..5ed00425a75
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-077.md
@@ -0,0 +1,288 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca2a
+title: Step 77
+challengeType: 0
+dashedName: step-77
+---
+
+# --description--
+
+Add the three functions necessary to append the new circle elements. Remember that they won't actually be visible yet.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg circle').length === 27);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-078.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-078.md
new file mode 100644
index 00000000000..fea82b1f06f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-078.md
@@ -0,0 +1,296 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca2b
+title: Step 78
+challengeType: 0
+dashedName: step-78
+---
+
+# --description--
+
+Appropriately set the `cx` and `cy` attributes for the Instagram circles.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('svg circle')[18].getAttribute('cx') == '70' &&
+ $('svg circle')[18].getAttribute('cy') == '424.024'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-079.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-079.md
new file mode 100644
index 00000000000..36c953d0596
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-079.md
@@ -0,0 +1,302 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca2c
+title: Step 79
+challengeType: 0
+dashedName: step-79
+---
+
+# --description--
+
+Appropriately set the radius (`r`), `fill`, and `stroke` for these circles.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('svg circle')[18].getAttribute('r') == '6' &&
+ $('svg circle')[18].getAttribute('fill') === 'white' &&
+ $('svg circle')[18].getAttribute('stroke') === '#fd9b98'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-080.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-080.md
new file mode 100644
index 00000000000..08a57df3f2f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-080.md
@@ -0,0 +1,302 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca2d
+title: Step 80
+challengeType: 0
+dashedName: step-80
+---
+
+# --description--
+
+Apply the appropriate `cursor` style for these circles.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg circle')[18].style.cursor === 'pointer');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-081.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-081.md
new file mode 100644
index 00000000000..14ffc2dbaf6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-081.md
@@ -0,0 +1,309 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca2e
+title: Step 81
+challengeType: 0
+dashedName: step-81
+---
+
+# --description--
+
+The line graph is looking good. All the empty space to the right will be for the pie graph and legend. Create a new `const` named `rightDashboard` and set equal to `d3.select('.dashboard')`. This will select your dashboard container again which currently only has the SVG element as a child.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const\s*rightDashboard\s*=\s*d3\.select\s*\((`|'|")\.dashboard\1\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-082.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-082.md
new file mode 100644
index 00000000000..ef8009859e8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-082.md
@@ -0,0 +1,312 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca2f
+title: Step 82
+challengeType: 0
+dashedName: step-82
+---
+
+# --description--
+
+Use `append` to add a `div` element to the selection. This will put a div as another child of the dashboard container to hold the pie graph and legend.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const rightDashboard = d3\.select\((`|'|")\.dashboard\1\)\s*\.append\s*\(\s*(`|'|")div\2\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-083.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-083.md
new file mode 100644
index 00000000000..43e8ea22992
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-083.md
@@ -0,0 +1,315 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca30
+title: Step 83
+challengeType: 0
+dashedName: step-83
+---
+
+# --description--
+
+Create a new `const` named `pieGraph` and set it equal to `rightDashboard.append('svg')`. This will add an SVG element for the pie graph as a child of the div you just added. The pie graph will have three slices, one for each platform. It will display a percentage of how many followers each platform has for the displayed year.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const\s*pieGraph\s*=\s*rightDashboard\s*\.\s*append\s*\((`|'|")svg\1\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-084.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-084.md
new file mode 100644
index 00000000000..1e01a5f30ff
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-084.md
@@ -0,0 +1,318 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca31
+title: Step 84
+challengeType: 0
+dashedName: step-84
+---
+
+# --description--
+
+Add two `attr` functions that set the `width` and `height` of the new SVG to `200`.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('svg')[1].getAttribute('width') == '200' &&
+ $('svg')[1].getAttribute('height') == '200'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-085.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-085.md
new file mode 100644
index 00000000000..33057ce9acc
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-085.md
@@ -0,0 +1,319 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca32
+title: Step 85
+challengeType: 0
+dashedName: step-85
+---
+
+# --description--
+
+Create a new `const` named `pieArc` and set it equal to `d3.arc()`. This will be used to create the angles for the lines of the pie chart using the D3 arc generator.
+
+# --hints--
+
+test-text
+
+```js
+assert(/const\s*pieArc\s*=\s*d3\s*\.\s*arc\s*\(\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-086.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-086.md
new file mode 100644
index 00000000000..fc228825cc5
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-086.md
@@ -0,0 +1,324 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca33
+title: Step 86
+challengeType: 0
+dashedName: step-86
+---
+
+# --description--
+
+Chain the function `outerRadius(100)` to the arc. This will set the outer radius of the pie chart to 100.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const pieArc = d3\.arc\(\)\s*\.\s*outerRadius\s*\(\s*100\s*\)/g.test(code)
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-087.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-087.md
new file mode 100644
index 00000000000..bf1d3f754da
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-087.md
@@ -0,0 +1,328 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca34
+title: Step 87
+challengeType: 0
+dashedName: step-87
+---
+
+# --description--
+
+Chain `innerRadius` to the arc and pass it `0` (zero). This is set to zero to make a traditional pie chart, you would use a larger inner radius to create a doughnut chart.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const pieArc = d3\.arc\(\)\s*\.outerRadius\(100\)\s*\.\s*innerRadius\s*\(\s*0\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-088.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-088.md
new file mode 100644
index 00000000000..73bf1cd804a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-088.md
@@ -0,0 +1,329 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca35
+title: Step 88
+challengeType: 0
+dashedName: step-88
+---
+
+# --description--
+
+The pie chart needs a new scale to set the colors. Create a new `const` named `pieColors` and set it equal to `d3.scaleOrdinal()`. An ordinal scale is for a set of data that will have exactly one item in the range specifically for it.
+
+In this case, each platform of followers you have will map directly to a single color with nothing in between.
+
+# --hints--
+
+test-text
+
+```js
+assert(/const\s*pieColors\s*=\s*d3\s*\.\s*scaleOrdinal\s*\(\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-089.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-089.md
new file mode 100644
index 00000000000..20900e45822
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-089.md
@@ -0,0 +1,334 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca36
+title: Step 89
+challengeType: 0
+dashedName: step-89
+---
+
+# --description--
+
+Set the `domain` of the scale to `data[8].followers`. This will be three items, one for each platform.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const pieColors = d3\.scaleOrdinal\(\)\s*\.\s*domain\s*\(\s*data\s*\[\s*8\s*\]\s*\.\s*followers\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-090.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-090.md
new file mode 100644
index 00000000000..a4a80c7f95d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-090.md
@@ -0,0 +1,336 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca37
+title: Step 90
+challengeType: 0
+dashedName: step-90
+---
+
+# --description--
+
+Since the domain has three items, the range also needs to have three items. If it had less, the values would repeat, putting the same color on the pie chart multiple times. Add the `range` function to the scale and pass it an array with your three color variables. Put them in the same order in which they are defined.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /\.domain\(data\[8\]\.followers\)\s*\.\s*range\s*\(\s*\[\s*twitterColor\s*,\s*tumblrColor\s*,\s*instagramColor\s*\]\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-091.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-091.md
new file mode 100644
index 00000000000..8a4e9aab0a3
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-091.md
@@ -0,0 +1,335 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca38
+title: Step 91
+challengeType: 0
+dashedName: step-91
+---
+
+# --description--
+
+Create a new `const` named `pie` and set it equal to `d3.pie()`. This is the D3 pie chart generator.
+
+# --hints--
+
+test-text
+
+```js
+assert(/const\s*pie\s*=\s*d3\s*\.\s*pie\s*\(\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-092.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-092.md
new file mode 100644
index 00000000000..84edb9a9490
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-092.md
@@ -0,0 +1,344 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca39
+title: Step 92
+challengeType: 0
+dashedName: step-92
+---
+
+# --description--
+
+Chain a `value` function to `pie` and pass it `d => d.value`. Each piece of data(`d`) will have a `key`(platform) and a `value`(number of followers), you want to return the number of followers here. The pie function will create an array of objects from these values that describe the angles and sizes the pie chart needs.
+
+In a few steps, you will make an array out of your data variable that will be passed to this function.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const pie = d3\.pie\(\)\s*\.\s*value\s*\(\s*d\s*=>\s*d\.value\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-093.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-093.md
new file mode 100644
index 00000000000..781851c9440
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-093.md
@@ -0,0 +1,345 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca3a
+title: Step 93
+challengeType: 0
+dashedName: step-93
+---
+
+# --description--
+
+Create a new `const` named `pieGraphData` and set the value equal to `pieGraph.selectAll('pieSlices')`. This is an empty selection similar circles you created earlier.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const\s*pieGraphData\s*=\s*pieGraph\s*\.\s*selectAll\s*\(\s*(`|'|")pieSlices\1\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-094.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-094.md
new file mode 100644
index 00000000000..58dc3df6029
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-094.md
@@ -0,0 +1,348 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca3b
+title: Step 94
+challengeType: 0
+dashedName: step-94
+---
+
+# --description--
+
+Add the `data` function to the selection. Pass it your `pie` function with an empty array as its argument for now. The next step will get the correct array to put there.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const pieGraphData = pieGraph\.selectAll\((`|'|")pieSlices\1\)\s*\.\s*data\s*\(pie\s*\(\s*\[\s*\]\s*\)\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-095.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-095.md
new file mode 100644
index 00000000000..857d79ad14b
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-095.md
@@ -0,0 +1,367 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca3c
+title: Step 95
+challengeType: 0
+dashedName: step-95
+---
+
+# --description--
+
+You want the array passed to `pie` to be an array of key/value objects for the 2020 followers. `d3.entries` will build that array for you. Here's how that looks:
+
+```js
+d3.entries(data[8].followers))
+```
+
+The array it builds looks like this:
+
+```js
+[
+ { key: 'twitter', value: 2845 },
+ { key: 'tumblr', value: 2040 },
+ { key: 'instagram', value: 4801 }
+]
+```
+
+This is where the `value` comes from in your `pie` variable.
+
+Add the `d3.entries` function as your `pie` argument. Use it to create the above array.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const pieGraphData = pieGraph\.selectAll\((`|'|")pieSlices\1\)\s*\.\s*data\s*\(pie\s*\(\s*d3\s*\.\s*entries\s*\(\s*data\s*\[\s*8\s*\]\s*\.\s*followers\s*\)\s*\)\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-096.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-096.md
new file mode 100644
index 00000000000..19400c8460f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-096.md
@@ -0,0 +1,350 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca3d
+title: Step 96
+challengeType: 0
+dashedName: step-96
+---
+
+# --description--
+
+Add the `enter` function to the current selection. Just like before, the initial selection here has a length of zero and the data has a length of three. So when you append elements in the next step, three will be created; one for each slice of the pie.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /\.data\(pie\(d3\.entries\(data\[8\]\.followers\)\)\)\s*\.\s*enter\s*\(\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-097.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-097.md
new file mode 100644
index 00000000000..b94dc14b7b7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-097.md
@@ -0,0 +1,348 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca3e
+title: Step 97
+challengeType: 0
+dashedName: step-97
+---
+
+# --description--
+
+Use `append` to add three `g` elements for the pie.
+
+# --hints--
+
+test-text
+
+```js
+assert($('svg g').length === 20);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-098.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-098.md
new file mode 100644
index 00000000000..8b1e882f741
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-098.md
@@ -0,0 +1,351 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca3f
+title: Step 98
+challengeType: 0
+dashedName: step-98
+---
+
+# --description--
+
+On a new line, `append` a `path` element to your `pieGraphData` variable. This is where you will start to draw the pie chart.
+
+# --hints--
+
+test-text
+
+```js
+assert(/pieGraphData\s*\.\s*append\s*\((`|'|")path\1\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-099.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-099.md
new file mode 100644
index 00000000000..7c2fdc874d7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-099.md
@@ -0,0 +1,352 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca40
+title: Step 99
+challengeType: 0
+dashedName: step-99
+---
+
+# --description--
+
+Set the `d` attribute to your `pieArc` variable. Just like the `d` in your lines, this is an SVG attribute for path elements that describes how to draw things. Your `pieArc` variable will determine what this value is for you.
+
+# --hints--
+
+test-text
+
+```js
+assert($('.dashboard div svg path')[0].getAttribute('d').length === 94);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-100.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-100.md
new file mode 100644
index 00000000000..ff80e8cbead
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-100.md
@@ -0,0 +1,372 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca41
+title: Step 100
+challengeType: 0
+dashedName: step-100
+---
+
+# --description--
+
+The pie graph is being drawn at the `0, 0` coordinates of the SVG. Back on your `pieGraphData` variable, add an attribute that changes the `transform` to `translate(100, 100)`.
+
+Since the pie chart has a radius of 100, and the SVG is 200 by 200, this will move it so it is centered.
+
+# --hints--
+
+test-text
+
+```js
+const transform = $('.dashboard div svg g')[0].getAttribute('transform');
+assert(/translate\s*\(\s*100\s*,\s*100\s*\)/g.test(transform));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-101.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-101.md
new file mode 100644
index 00000000000..69a67b1c697
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-101.md
@@ -0,0 +1,377 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca42
+title: Step 101
+challengeType: 0
+dashedName: step-101
+---
+
+# --description--
+
+Back at the bottom, where you draw the chart. Use the `attr` function to set the `fill` to a "d function". In the "d function", use your `pieColors` scale to get the color value for the platform(`d.data.key`). So when each platform is passed to your scale, is will get the appropriate color to use as the fill from the scales range.
+
+# --hints--
+
+test-text
+
+```js
+const pathsArr = $('.dashboard div svg g path');
+assert(
+ pathsArr[0].getAttribute('fill') === '#7cd9d1' &&
+ pathsArr[1].getAttribute('fill') === '#f6dd71' &&
+ pathsArr[2].getAttribute('fill') === '#fd9b98'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-102.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-102.md
new file mode 100644
index 00000000000..c35673b4338
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-102.md
@@ -0,0 +1,364 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca43
+title: Step 102
+challengeType: 0
+dashedName: step-102
+---
+
+# --description--
+
+Next, set the `stroke` to `white` and the `stroke-width` to `2`.
+
+# --hints--
+
+test-text
+
+```js
+const pathsArr = $('.dashboard div svg g path');
+assert(
+ pathsArr[0].getAttribute('stroke') === 'white' &&
+ pathsArr[0].getAttribute('stroke-width') == 2
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-103.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-103.md
new file mode 100644
index 00000000000..b4d01a98916
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-103.md
@@ -0,0 +1,365 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca44
+title: Step 103
+challengeType: 0
+dashedName: step-103
+---
+
+# --description--
+
+Your chart needs some labels in each slice. On a new line, append `text` elements to your `pieGraphData` variable.
+
+# --hints--
+
+test-text
+
+```js
+assert(/pieGraphData\s*\.\s*append\s*\((`|'|")text\1\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-104.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-104.md
new file mode 100644
index 00000000000..f3f23bf2a8c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-104.md
@@ -0,0 +1,381 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca47
+title: Step 104
+challengeType: 0
+dashedName: step-104
+---
+
+# --description--
+
+Chain a `text` function to set the text of each pie slice to a percentage. Set the value to a "d function" with curly brackets and leave the function empty for now. It should look like this:
+
+```js
+.text(d => {
+
+})
+```
+
+The method for getting the percent of each slice will take a few steps:
+
+1. Find the total number of followers for the displayed year
+2. Divide the followers of a single platform by that total
+3. Turn it into a string to display
+
+# --hints--
+
+test-text
+
+```js
+assert(/\.append\('text'\)\s*\.text\s*\(\s*d\s*=>\s*\{\s*\}\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-105.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-105.md
new file mode 100644
index 00000000000..7dd7bc8f459
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-105.md
@@ -0,0 +1,383 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca48
+title: Step 105
+challengeType: 0
+dashedName: step-105
+---
+
+# --description--
+
+In the function you just created, create a `const` named `values`. Use the `d3.values` function to get the values of the 2020 followers and set the result to your `values` variable. Here's how to get the values:
+
+```js
+d3.values(data[8].followers)
+```
+
+It will be an array with the values of the followers for the three platforms in 2020.
+
+Note that this "d function" has curly brackets. So you could `console.log(values)` in there to see it's value.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const\s*values\s*=\s*d3\s*\.\s*values\s*\(\s*data\s*\[\s*8\s*\]\s*\.\s*followers\s*\);?/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-106.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-106.md
new file mode 100644
index 00000000000..1e304f5fbb6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-106.md
@@ -0,0 +1,372 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca49
+title: Step 106
+challengeType: 0
+dashedName: step-106
+---
+
+# --description--
+
+Since you want to find what percent each of those `values` is, you first need to add them all up. `d3.sum` will do that for you. Create a new `const` named `sum` and set it equal to `d3.sum(values)`.
+
+# --hints--
+
+test-text
+
+```js
+assert(/const\s*sum\s*=\s*d3\s*\.\s*sum\s*\(\s*values\s*\)\s*;?/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-107.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-107.md
new file mode 100644
index 00000000000..9fcc056c466
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-107.md
@@ -0,0 +1,376 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca4a
+title: Step 107
+challengeType: 0
+dashedName: step-107
+---
+
+# --description--
+
+Create another variable named `percent` and set it equal to `d.data.value` divided by your `sum` variable.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const\s*percent\s*=\s*d\s*\.\s*data\s*\.\s*value\s*\/\s*sum;?/g.test(code)
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-108.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-108.md
new file mode 100644
index 00000000000..124a7abec7e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-108.md
@@ -0,0 +1,388 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca4b
+title: Step 108
+challengeType: 0
+dashedName: step-108
+---
+
+# --description--
+
+Your percent values are numbers less than one. You will need to multiply it by 100, round of the decimals, and add a `%` sign. Use a template literal to return this to the `text` function:
+
+```js
+${Math.round(percent * 100)}%
+```
+
+Don't forget that you need a `return` statement here since you aren't using an implicit return.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /return\s*`\$\{\s*Math\s*\.\s*round\s*\(\s*percent\s*\*\s*100\s*\)\s*\}%`;?\s*\}\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-109.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-109.md
new file mode 100644
index 00000000000..de9a3090429
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-109.md
@@ -0,0 +1,388 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca4c
+title: Step 109
+challengeType: 0
+dashedName: step-109
+---
+
+# --description--
+
+The text elements are at the center of the pie graph, you need to use the `centroid` from the D3 arc API to tell them where to go. Add an `attr` function to set the `transform` to a `d` function that returns this template literal: `translate(${ pieArc.centroid(d) })`
+
+The `centroid` function will find the midpoint of each slice for each text element.
+
+# --hints--
+
+test-text
+
+```js
+const transform = $('.dashboard div svg g text')[0]
+ .getAttribute('transform')
+ .replace('translate(', '')
+ .replace(')', '')
+ .split(',');
+assert(transform[0] < 39 && transform[1] > 31);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-110.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-110.md
new file mode 100644
index 00000000000..cfe05994783
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-110.md
@@ -0,0 +1,389 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca4d
+title: Step 110
+challengeType: 0
+dashedName: step-110
+---
+
+# --description--
+
+The function you just added, placed the start of the text at the midpoint of each slice. Change the `style` of the text to give it a `text-anchor` of `middle` so the middle of the text is in the middle of the slice.
+
+After that, set the `font` to `10px verdana`.
+
+# --hints--
+
+test-text
+
+```js
+const text = $('.dashboard div svg g text')[0];
+assert(
+ text.style.textAnchor === 'middle' &&
+ text.style.font.toLowerCase() === '10px verdana'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-111.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-111.md
new file mode 100644
index 00000000000..5a6cda0ba57
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-111.md
@@ -0,0 +1,391 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca4e
+title: Step 111
+challengeType: 0
+dashedName: step-111
+---
+
+# --description--
+
+The last component you are going to add is a legend to display the name of each platform and the number of followers for the year. Create a new `const` named `legend` and use it to `append` a `table` to your `rightDashboard` variable. This looks similar to the code where you created your `pieGraph` variable.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const\s*legend\s*=\s*rightDashboard\s*\.\s*append\s*\(\s*('|"|`)\s*table\s*\1\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-112.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-112.md
new file mode 100644
index 00000000000..be844c9e21c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-112.md
@@ -0,0 +1,394 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca4f
+title: Step 112
+challengeType: 0
+dashedName: step-112
+---
+
+# --description--
+
+Give the table a `width` of `200` and a `height` of `120` using `attr`.
+
+# --hints--
+
+test-text
+
+```js
+const table = $('.dashboard div table')[0];
+assert(
+ table.getAttribute('width') == 200 && table.getAttribute('height') == 120
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-113.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-113.md
new file mode 100644
index 00000000000..439b742b887
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-113.md
@@ -0,0 +1,396 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca50
+title: Step 113
+challengeType: 0
+dashedName: step-113
+---
+
+# --description--
+
+Set the `font` to `12px verdana` using the `style` function.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('.dashboard div table')[0].style.font.toLowerCase() === '12px verdana'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-114.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-114.md
new file mode 100644
index 00000000000..1be90df8df5
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-114.md
@@ -0,0 +1,401 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca51
+title: Step 114
+challengeType: 0
+dashedName: step-114
+---
+
+# --description--
+
+Create a new `const` named `legendTitle` and use it to `append` a `thead` to your `legend` variable. `thead` is used with the HTML table element and is for the top row of the table.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const\s*legendTitle\s*=\s*legend\s*\.\s*append\s*\(\s*('|"|`)\s*thead\s*\1\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-115.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-115.md
new file mode 100644
index 00000000000..df269c6462c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-115.md
@@ -0,0 +1,401 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca52
+title: Step 115
+challengeType: 0
+dashedName: step-115
+---
+
+# --description--
+
+`append` a `tr` element to the selection and then append a `th` element right after it. `tr` is for defining a row of the table, and `th` is for defining the header cells of the table.
+
+# --hints--
+
+test-text
+
+```js
+assert($('.dashboard div table thead tr th').length === 1);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-116.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-116.md
new file mode 100644
index 00000000000..eb6c7d09187
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-116.md
@@ -0,0 +1,404 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca53
+title: Step 116
+challengeType: 0
+dashedName: step-116
+---
+
+# --description--
+
+Use the `text` function to set the text of the selection to `2020 followers`.
+
+# --hints--
+
+test-text
+
+```js
+assert($('.dashboard div table thead tr th').text() === '2020 followers');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-117.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-117.md
new file mode 100644
index 00000000000..7c19f3dcae6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-117.md
@@ -0,0 +1,406 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca54
+title: Step 117
+challengeType: 0
+dashedName: step-117
+---
+
+# --description--
+
+Your table is going to have three columns, one for the platform name, one for the color it is using on your dashboard, and a third to display the number of followers. So you want the title to take up all three columns. Set the `colspan` attribute of the `th` to `3` so it spans all three of these columns.
+
+# --hints--
+
+test-text
+
+```js
+assert($('.dashboard div table thead tr th')[0].getAttribute('colspan') == 3);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-118.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-118.md
new file mode 100644
index 00000000000..0cfe9b5a70a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-118.md
@@ -0,0 +1,412 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca55
+title: Step 118
+challengeType: 0
+dashedName: step-118
+---
+
+# --description--
+
+Create a new `const` named `legendRows` and use it to `append` a `tbody` element to your `legend` variable similar to how you added the `thead`. `tbody` is for the main content of an HTML table.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const\s*legendRows\s*=\s*legend\s*\.\s*append\s*\(\s*('|"|`)\s*tbody\s*\1\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-119.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-119.md
new file mode 100644
index 00000000000..bcdec5c5339
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-119.md
@@ -0,0 +1,417 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca56
+title: Step 119
+challengeType: 0
+dashedName: step-119
+---
+
+# --description--
+
+Add a `selectAll` function to the selection and pass it the string `tr`.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /const legendRows = legend\.append\('tbody\s*'\)\s*\.\s*selectAll\s*\(\s*('|"|`)\s*tr\s*\1\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-120.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-120.md
new file mode 100644
index 00000000000..4ee832321fb
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-120.md
@@ -0,0 +1,417 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca57
+title: Step 120
+challengeType: 0
+dashedName: step-120
+---
+
+# --description--
+
+Use the `data` function to set the data for the rows to an array of your 2020 followers. To get the array use `d3.entries(data[8].followers)`. Remember, this will create an array of key/value pairs of your followers for that year.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ /\.selectAll\('tr'\)\s*\.\s*data\s*\(\s*d3\s*\.\s*entries\s*\(\s*data\s*\[\s*8\s*\]\s*\.\s*followers\s*\)\s*\)/g.test(
+ code
+ )
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-121.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-121.md
new file mode 100644
index 00000000000..e03bdbdb791
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-121.md
@@ -0,0 +1,418 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca58
+title: Step 121
+challengeType: 0
+dashedName: step-121
+---
+
+# --description--
+
+Add the `enter` and `append` functions to the selection. Pass the string `tr` to the append function to add three table row elements. These elements will be for displaying each platform's name.
+
+# --hints--
+
+test-text
+
+```js
+assert($('.dashboard div table tbody tr').length === 3);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-122.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-122.md
new file mode 100644
index 00000000000..ed855f5024f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-122.md
@@ -0,0 +1,422 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca59
+title: Step 122
+challengeType: 0
+dashedName: step-122
+---
+
+# --description--
+
+On a new line, `append` a `td` to your `legendRows` variable. `td` is for an individual cell in the row of the table.
+
+# --hints--
+
+test-text
+
+```js
+assert($('.dashboard div table tbody tr td').length === 3);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-123.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-123.md
new file mode 100644
index 00000000000..7c8fd63c36c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-123.md
@@ -0,0 +1,426 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca5a
+title: Step 123
+challengeType: 0
+dashedName: step-123
+---
+
+# --description--
+
+Use the `text` function to set the text of each `td` to the `key` of each data point by using a "d function" to return `d.key`.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('.dashboard div table tbody tr td').text() === 'twittertumblrinstagram'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-124.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-124.md
new file mode 100644
index 00000000000..721d4428093
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-124.md
@@ -0,0 +1,431 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca5b
+title: Step 124
+challengeType: 0
+dashedName: step-124
+---
+
+# --description--
+
+This is the first column of your table. Set the `align` attribute to `right` to align the text to the right of each cell.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('.dashboard div table tbody tr td')[0]
+ .getAttribute('align')
+ .toLowerCase() === 'right'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-125.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-125.md
new file mode 100644
index 00000000000..565a8dc72fe
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-125.md
@@ -0,0 +1,430 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca5c
+title: Step 125
+challengeType: 0
+dashedName: step-125
+---
+
+# --description--
+
+On a new line, append another `td` element to your `legendRows` variable. This will be for colored squares in the center column.
+
+# --hints--
+
+test-text
+
+```js
+assert($('.dashboard div table tbody tr td').length === 6);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-126.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-126.md
new file mode 100644
index 00000000000..cb21e05cc6a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-126.md
@@ -0,0 +1,437 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca5d
+title: Step 126
+challengeType: 0
+dashedName: step-126
+---
+
+# --description--
+
+Set the `align` attribute to `center`.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('.dashboard div table tbody tr td')[1]
+ .getAttribute('align')
+ .toLowerCase() === 'center'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-127.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-127.md
new file mode 100644
index 00000000000..90544de2a70
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-127.md
@@ -0,0 +1,435 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca5e
+title: Step 127
+challengeType: 0
+dashedName: step-127
+---
+
+# --description--
+
+Append a `div` element to the selection. Each `div` will be a small square for each color.
+
+# --hints--
+
+test-text
+
+```js
+assert($('.dashboard div table tbody tr td div').length === 3);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-128.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-128.md
new file mode 100644
index 00000000000..bd8711a89b8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-128.md
@@ -0,0 +1,438 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca5f
+title: Step 128
+challengeType: 0
+dashedName: step-128
+---
+
+# --description--
+
+Set the `width` to `16px` and the `height` to `16px` using the `style` function.
+
+# --hints--
+
+test-text
+
+```js
+const div = $('.dashboard div table tbody tr td div')[0];
+assert(div.style.width == '16px' && div.style.height === '16px');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-129.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-129.md
new file mode 100644
index 00000000000..3c351a7399a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-129.md
@@ -0,0 +1,443 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca60
+title: Step 129
+challengeType: 0
+dashedName: step-129
+---
+
+# --description--
+
+Using the `style` function again, set the `background-color` of each div to a "d function". Using the "d function", pass the key(`d.key`) of each data point to your `pieColors` scale so it knows what color to use.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('.dashboard div table tbody tr td div')[0].style.backgroundColor ===
+ 'rgb(124, 217, 209)'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-130.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-130.md
new file mode 100644
index 00000000000..bace7d9779c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-130.md
@@ -0,0 +1,443 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca61
+title: Step 130
+challengeType: 0
+dashedName: step-130
+---
+
+# --description--
+
+On a new line, append another `td` to the `legendRows` variable for the last group of items. It will display the number of followers for each platform.
+
+# --hints--
+
+test-text
+
+```js
+assert($('.dashboard div table tbody tr td').length === 9);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-131.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-131.md
new file mode 100644
index 00000000000..e508369e164
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-131.md
@@ -0,0 +1,446 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca62
+title: Step 131
+challengeType: 0
+dashedName: step-131
+---
+
+# --description--
+
+Set the `text` to a "d function" that returns the value(`d.value`) for each data point.
+
+# --hints--
+
+test-text
+
+```js
+assert($('.dashboard div table tbody tr td')[2].innerHTML === '2845');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-132.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-132.md
new file mode 100644
index 00000000000..d3f68fb936c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-132.md
@@ -0,0 +1,450 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca63
+title: Step 132
+challengeType: 0
+dashedName: step-132
+---
+
+# --description--
+
+Set the `align` attribute to `left` for this selection.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ $('.dashboard div table tbody tr td')[2]
+ .getAttribute('align')
+ .toLowerCase() === 'left'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-133.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-133.md
new file mode 100644
index 00000000000..6fe0e8de953
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-133.md
@@ -0,0 +1,448 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca64
+title: Step 133
+challengeType: 0
+dashedName: step-133
+---
+
+# --description--
+
+The legend has all the information is needs, but the title looks a little misaligned. Go to where you created your `legendTitle` variable and set the `position` to `relative` and the `left` to `20px` using `style` functions.
+
+# --hints--
+
+test-text
+
+```js
+const th = $('.dashboard div table thead tr th')[0];
+assert(th.style.position === 'relative' && th.style.left === '20px');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-134.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-134.md
new file mode 100644
index 00000000000..03e36d189a6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-134.md
@@ -0,0 +1,453 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca65
+title: Step 134
+challengeType: 0
+dashedName: step-134
+---
+
+# --description--
+
+The legend and pie graph look a little off as well. Go to where you created your `legend` variable and add a `position` of `relative` and a `top` of `30px` using `style` functions.
+
+# --hints--
+
+test-text
+
+```js
+const table = $('.dashboard div table')[0];
+assert(table.style.position === 'relative' && table.style.top === '30px');
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-135.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-135.md
new file mode 100644
index 00000000000..a6c4b6fb870
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-135.md
@@ -0,0 +1,464 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca66
+title: Step 135
+challengeType: 0
+dashedName: step-135
+---
+
+# --description--
+
+Lastly, where you created your `pieGraph` variable, add a `position` of `relative` and a `left` of `20px` using `style` functions.
+
+# --hints--
+
+test-text
+
+```js
+const pieGraph = $('.dashboard div svg')[0];
+assert(
+ pieGraph.style.position === 'relative' && pieGraph.style.left === '20px'
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-136.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-136.md
new file mode 100644
index 00000000000..139d0e87f65
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-136.md
@@ -0,0 +1,476 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca67
+title: Step 136
+challengeType: 0
+dashedName: step-136
+---
+
+# --description--
+
+Finally! You have all the elements displayed and they look good. The last thing you will do is make it so you can see the data from whatever year you want.
+
+Wrap all the code in the script you've been working with in a function named `drawDashboard` and give it a parameter named `year`. Then, at the bottom of the script, call the function you created and pass it the number `2020`.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ typeof drawDashboard === 'function' &&
+ /<\/script>\s*
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-137.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-137.md
new file mode 100644
index 00000000000..a690b7567e6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-137.md
@@ -0,0 +1,479 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca68
+title: Step 137
+challengeType: 0
+dashedName: step-137
+---
+
+# --description--
+
+At the top of the function create a new `const` named `index`. You are going to use it to find the item in the `data` array with the year that is passed to the function.
+
+Use JavaScript's `findIndex` function to set your `index` variable to the index of the item in the `data` array where the year is the same as the year passed to your `drawDashboard` function. Here's an example:
+
+```js
+array.findIndex(d =>
+ // find the index where the year passed to
+ // drawDashboard equals the year of the array
+)
+```
+
+After this, you will be able to use `data[index]` to get that item in the array.
+
+# --hints--
+
+test-text
+
+```js
+assert.match(code,/const index = data.findIndex\(\(?d\)? => (year === d\.year|d.year === year)\s*\)/g);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-138.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-138.md
new file mode 100644
index 00000000000..054da5d15a2
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-138.md
@@ -0,0 +1,479 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca6a
+title: Step 138
+challengeType: 0
+dashedName: step-138
+---
+
+# --description--
+
+There are four places in the file where you used `data[8]` to set data to the year 2020. Change all five of them to `data[index]` so you can pass in any year to the function to display the data from that year.
+
+The five spots are:
+
+1. The `domain` for `pieColors`.
+2. The `data` for `pieGraphData`.
+3. The `text` for your pie slice text.
+4. The `data` for your `legendRows`.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ !/data\[8\]/g.test(code) && code.match(/data\s*\[\s*index\s*\]/g).length === 4
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-139.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-139.md
new file mode 100644
index 00000000000..5630a5404bb
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-139.md
@@ -0,0 +1,482 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca6b
+title: Step 139
+challengeType: 0
+dashedName: step-139
+---
+
+# --description--
+
+Go to where you `call` the `xAxis` and create a `mouseover` event for the labels. Chain the `on` function to them, pass it the string `mouseover`, and give it a value of a "d function" that calls `drawDashboard` with `d` as the argument. It will look like this:
+
+```js
+.on('mouseover', d => drawDashboard(d))
+```
+
+So now, when you hover a label, the function will be called with the year that is being hovered.
+
+# --hints--
+
+test-text
+
+```js
+assert.match(code,
+ /\.on\('mouseover', d => drawDashboard\(d\)\)/g
+ );
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-140.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-140.md
new file mode 100644
index 00000000000..45fd59a633e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-140.md
@@ -0,0 +1,477 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca6c
+title: Step 140
+challengeType: 0
+dashedName: step-140
+---
+
+# --description--
+
+There's a problem, each time you hover a label it adds all the elements to the container again. If you empty the container at the top of the function, it will redraw them where they need to be.
+
+Go back to the top of the function and use `d3.select` to select the `.dashboard` element and chain the `html` function to it with an empty string as it parameter. Empty means no spaces.
+
+# --hints--
+
+test-text
+
+```js
+assert.match(code, /d3\.select\(('|"|`)\.dashboard\1\)\.html\(('|"|`)\2\)/g);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-141.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-141.md
new file mode 100644
index 00000000000..0c9593756d7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-141.md
@@ -0,0 +1,489 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca6d
+title: Step 141
+challengeType: 0
+dashedName: step-141
+---
+
+# --description--
+
+Now when you hover a label, you can see the data for the different years.
+
+Where you created the `text` elements for the x-axis labels, change the `font` to `bold 10px verdana` for the currently displayed year.
+
+To do this, create a "d function" in the `font` value area and return the above sting if `d` equals `year`. Otherwise, return the string that is currently there (`10px verdana`). It's easiest to use a ternary operator for this.
+
+Here's a hint:
+
+```js
+.style('font', d => d === year ? )
+```
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ Object.values($('.dashboard svg g text')).filter(
+ (el) => el.style && el.style.font.toLowerCase() === 'bold 10px verdana'
+ ).length === 1
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-142.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-142.md
new file mode 100644
index 00000000000..bee3e7b5989
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-142.md
@@ -0,0 +1,478 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca6e
+title: Step 142
+challengeType: 0
+dashedName: step-142
+---
+
+# --description--
+
+Create another `mouseover` event for when you hover one of the `twitter-circles`. It will look like the other `mouseover` event you created except the `drawDashboard` function will take `d.year` instead of `d`.
+
+# --hints--
+
+test-text
+
+```js
+assert.match(code,
+ /\.on\('mouseover', d => drawDashboard\(d\.year\)\)/
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-143.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-143.md
new file mode 100644
index 00000000000..0cfeac007dc
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-143.md
@@ -0,0 +1,483 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca6f
+title: Step 143
+challengeType: 0
+dashedName: step-143
+---
+
+# --description--
+
+Similar to how you made the text bold for the label of the displayed year; change the `fill` of the `twitter-circles` to your `twitterColor` for the currently displayed year. To do this, use a "d function" that returns the `twitterColor` when `d.year` equals `year`, and leave it `white` if it doesn't.
+
+# --hints--
+
+test-text
+
+```js
+assert(
+ Object.values($('.dashboard svg circle')).filter(
+ (el) => el.getAttribute && el.getAttribute('fill') === '#7cd9d1'
+ ).length === 1
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-144.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-144.md
new file mode 100644
index 00000000000..97348bc5be8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-144.md
@@ -0,0 +1,489 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca70
+title: Step 144
+challengeType: 0
+dashedName: step-144
+---
+
+# --description--
+
+Add a `mouseover` event to the `tumblr-circles` and `instagram-circles` in the same way that you did for the `twitter-circles`.
+
+After that, you will be able hover any of the circles or year labels to get the information for that year.
+
+# --hints--
+
+test-text
+
+```js
+assert.equal(
+ code.match(
+ /\.on\('mouseover', d => drawDashboard\(d\.year\)\)/g
+ )?.length, 3
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-145.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-145.md
new file mode 100644
index 00000000000..3bf1fb49e15
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-145.md
@@ -0,0 +1,494 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca71
+title: Step 145
+challengeType: 0
+dashedName: step-145
+---
+
+# --description--
+
+Change the `fill` of the `tumblr-circles` and `instagram-circles` to use a "d function" that returns their respective color variables when `d.year` equals `year`, leave it `white` when they don't. This is similar to how you set the fill of the Twitter circles.
+
+Then, all of the circles will get filled in for the currently displayed year.
+
+# --hints--
+
+test-text
+
+```js
+const circles = Object.values($('.dashboard svg circle'));
+assert(
+ circles.filter(
+ (el) =>
+ el.getAttribute &&
+ (el.getAttribute('fill') === '#7cd9d1' ||
+ el.getAttribute('fill') === '#f6dd71' ||
+ el.getAttribute('fill') === '#fd9b98')
+ ).length === 3
+);
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-146.md b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-146.md
new file mode 100644
index 00000000000..d9c3208306e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/04-data-visualization/d3-dashboard/step-146.md
@@ -0,0 +1,483 @@
+---
+id: 5d8a4cfbe6b6180ed9a1ca72
+title: Step 146
+challengeType: 0
+dashedName: step-146
+---
+
+# --description--
+
+The last thing is that the legend title always shows 2020. Change the `text` of the `legendTitle` to a template literal that shows the currently displayed year followed by a space and `followers`.
+
+That's it, your dashboard is finished! Don't forget to admire your hard work.
+
+# --hints--
+
+test-text
+
+```js
+assert(/\.text\s*\(\s*`\s*\$\{\s*year\s*\} followers`\s*\)/g.test(code));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+ D3 Dashboard
+
+
+
+
+
+
+
+```
+
+## --seed-contents--
+
+```html
+
+
+```
+
+# --solutions--
+
+```html
+
+
+```
diff --git a/curriculum/challenges/chinese-traditional/10-coding-interview-prep/algorithms/implement-binary-search.md b/curriculum/challenges/chinese-traditional/10-coding-interview-prep/algorithms/implement-binary-search.md
new file mode 100644
index 00000000000..bd2e8306ee1
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/10-coding-interview-prep/algorithms/implement-binary-search.md
@@ -0,0 +1,155 @@
+---
+id: 61abc7ebf3029b56226de5b6
+title: Implement Binary Search
+challengeType: 1
+forumTopicId: 487618
+dashedName: implement-binary-search
+---
+
+# --description--
+
+Binary search is an **O(log(n))** efficiency algorithm for searching a sorted array to find an element. It operates using the following steps:
+
+1. Find the middle `value` of a sorted array. If `value == target` return (found it!).
+1. If middle `value < target`, search right half of array in next compare.
+1. If middle `value > target`, search left half of array in next compare.
+
+As you can see, you are successively halving an array, which gives you the log(n) efficiency. For this challenge, we want you to show your work - how you got to the target value... the path you took!
+
+# --instructions--
+
+Write a function `binarySearch` that implements the binary search algorithm on an array, returning the path you took (each middle value comparison) to find the target in an array.
+
+The function takes a sorted array of integers and a target value as input. It returns an array containing (in-order) the middle value you found at each halving of the original array until you found the target value. The target value should be the last element of the returned array. If value not is found, return the string `Value Not Found`.
+
+For example, `binarySearch([1,2,3,4,5,6,7], 5)` would return `[4,6,5]`.
+
+For this challenge, when halving, you MUST use `Math.floor()` when doing division: `Math.floor(x/2)`. This will give a consistent, testable path.
+
+**Note:** The following array will be used in tests:
+
+```js
+const testArray = [
+ 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 49, 70
+];
+```
+
+# --hints--
+
+`binarySearch` should be a function.
+
+```js
+assert(typeof binarySearch == 'function');
+```
+
+`binarySearch(testArray, 0)` should return `[13, 5, 2, 0]`.
+
+```js
+assert.deepEqual(binarySearch(_testArray, 0), [13, 5, 2, 0]);
+```
+
+`binarySearch(testArray, 1)` should return `[13, 5, 2, 0, 1]`.
+
+```js
+assert.deepEqual(binarySearch(_testArray, 1), [13, 5, 2, 0, 1]);
+```
+
+
+`binarySearch(testArray, 2)` should return `[13, 5, 2]`.
+
+```js
+assert.deepEqual(binarySearch(_testArray, 2), [13, 5, 2]);
+```
+
+`binarySearch(testArray, 6)` should return the string `Value Not Found`.
+
+```js
+assert.strictEqual(binarySearch(_testArray, 6), 'Value Not Found');
+```
+
+`binarySearch(testArray, 11)` should return `[13, 5, 10, 11]`.
+
+```js
+assert.deepEqual(binarySearch(_testArray, 11), [13, 5, 10, 11])
+```
+
+`binarySearch(testArray, 13)` should return `[13]`.
+
+```js
+assert.deepEqual(binarySearch(_testArray, 13), [13]);
+```
+
+`binarySearch(testArray, 70)` should return `[13, 19, 22, 49, 70]`.
+
+```js
+assert.deepEqual(binarySearch(_testArray, 70), [13, 19, 22, 49, 70]);
+```
+
+# --seed--
+
+## --after-user-code--
+
+```js
+const _testArray = [
+ 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 49, 70
+];
+```
+
+## --seed-contents--
+
+```js
+function binarySearch(searchList, value) {
+ let arrayPath = [];
+ return arrayPath;
+}
+```
+
+
+
+# --solutions--
+
+```js
+let binarySearch = (searchList, value) => {
+ let arrayPath = [];
+
+ // set initial L - M - R
+ let left = 0;
+ let right = searchList.length - 1;
+ let middle = Math.floor(right / 2);
+
+ // if first comparison finds value
+ if (searchList[middle] == value) {
+ arrayPath.push(searchList[middle]);
+ return arrayPath;
+ }
+
+ while (searchList[middle] !== value) {
+ // add to output array
+ arrayPath.push(searchList[middle]);
+
+ // not found
+ if (right < left) {
+ return 'Value Not Found';
+ }
+ // value is in left or right portion of array
+ // update L - M - R
+ if (searchList[middle] > value) {
+ right = middle - 1;
+ middle = left + Math.floor((right - left) / 2);
+ } else {
+ left = middle + 1;
+ middle = left + Math.floor((right - left) / 2);
+ }
+
+ // if found update output array and exit
+ if (searchList[middle] == value) {
+ arrayPath.push(searchList[middle]);
+
+ break;
+ }
+ }
+ return arrayPath;
+};
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a257659d0d1e2456f24ba2.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a257659d0d1e2456f24ba2.md
new file mode 100644
index 00000000000..12d385f3107
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a257659d0d1e2456f24ba2.md
@@ -0,0 +1,109 @@
+---
+id: 62a257659d0d1e2456f24ba2
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Before you start writing your project code, you should move it to its own file to keep things organized. Remove your `console.log("Hello World");` line. Then give your now empty `script` element a `src` attribute set to `./script.js`.
+
+# --hints--
+
+You should not have a `console.log("Hello World");` line in your code.
+
+```js
+assert.notMatch(code, /console\.log\("Hello World"\);/);
+```
+
+Your `script` element should have a `src` attribute set to `./script.js`.
+
+```js
+const script = document.querySelector("script[data-src$='script.js']");
+assert.exists(script);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a39f5a5790eb27c1e5d4bf.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a39f5a5790eb27c1e5d4bf.md
new file mode 100644
index 00000000000..af7153531cf
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a39f5a5790eb27c1e5d4bf.md
@@ -0,0 +1,102 @@
+---
+id: 62a39f5a5790eb27c1e5d4bf
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+Your view has been switched to your new `script.js` file. Remember that you can use the tabs above to switch between files.
+
+Add your `console.log("Hello World");` line to this file, and see it appear in your console.
+
+# --hints--
+
+You should have a `console.log("Hello World");` line in your code.
+
+```js
+assert.match(code, /console\.log\("Hello World"\);/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a0a3c0a4b32915d26a6e.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a0a3c0a4b32915d26a6e.md
new file mode 100644
index 00000000000..b40d5f4cc30
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a0a3c0a4b32915d26a6e.md
@@ -0,0 +1,132 @@
+---
+id: 62a3a0a3c0a4b32915d26a6e
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Remove your `console.log("Hello World");` line to begin writing your project code.
+
+In JavaScript, a variable is used to hold a value. To use a variable, you must first declare it. For example, to declare a variable called `camperbot`, you would write:
+
+```js
+var camperbot;
+```
+
+The `var` keyword tells JavaScript you are declaring a variable. Declare a variable called `xp`.
+
+# --hints--
+
+You should not have a `console.log("Hello World");` line in your code.
+
+```js
+assert.notMatch(code, /console\.log\("Hello World"\);/);
+```
+
+You should use the `var` keyword to declare your variable.
+
+```js
+assert.match(code, /var/);
+```
+
+You should declare a variable named `xp`.
+
+```js
+assert.match(code, /xp/);
+```
+
+You should not assign a value to your variable.
+
+```js
+assert.notMatch(code, /var xp =/);
+```
+
+Don't forget the semi-colon at the end of the line.
+
+```js
+assert.match(code, /var xp;/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+--fcc-editable-region--
+console.log("Hello World");
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a488b24fb32b91155d56.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a488b24fb32b91155d56.md
new file mode 100644
index 00000000000..7fb32406762
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a488b24fb32b91155d56.md
@@ -0,0 +1,112 @@
+---
+id: 62a3a488b24fb32b91155d56
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Variables can be assigned a value. When you do this while you declare it, this is called initialization. For example:
+
+```js
+var camperbot = "Bot";
+```
+
+This would initialize the `camperbot` variable with a value of `Bot`. Initialize your `xp` variable to have a value of `0`.
+
+# --hints--
+
+`xp` should have a value of `0`.
+
+```js
+assert.equal(xp, 0);
+```
+
+You should initialize the `xp` variable to `0`. Don't forget the semi-colon at the end of the line.
+
+```js
+assert.match(code, /var\s+xp\s*=\s*0\s*;/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+--fcc-editable-region--
+var xp;
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a75d8466a12e009eff76.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a75d8466a12e009eff76.md
new file mode 100644
index 00000000000..278aa0789fc
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a75d8466a12e009eff76.md
@@ -0,0 +1,136 @@
+---
+id: 62a3a75d8466a12e009eff76
+title: Step 21
+challengeType: 0
+dashedName: step-21
+---
+
+# --description--
+
+Initialize another variable called `health` with a value of `100`, and a variable called `gold` with a value of `50`.
+
+# --hints--
+
+You should use `var` to declare a variable called `health`.
+
+```js
+assert.match(code, /var health/);
+```
+
+You should initialize a variable called `health` with a value of `100`.
+
+```js
+assert.match(code, /var health\s?=\s?100/);
+```
+
+You should use `var` to declare a variable called `gold`.
+
+```js
+assert.match(code, /var gold/);
+```
+
+You should initialize a variable called `gold` with a value of `50`.
+
+```js
+assert.match(code, /var gold\s?=\s?50/);
+```
+
+`health` should have a value of `100`.
+
+```js
+assert.equal(health, 100);
+```
+
+`gold` should have a value of `50`.
+
+```js
+assert.equal(gold, 50);
+```
+
+`xp` should still have a value of `0`.
+
+```js
+assert.equal(xp, 0);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+--fcc-editable-region--
+var xp = 0;
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a7e4f1060e2fc5ffb34b.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a7e4f1060e2fc5ffb34b.md
new file mode 100644
index 00000000000..606fdeb799a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3a7e4f1060e2fc5ffb34b.md
@@ -0,0 +1,122 @@
+---
+id: 62a3a7e4f1060e2fc5ffb34b
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Create another variable called `currentWeapon` and set it to 0.
+
+When a variable name has multiple words, the convention in JavaScript is to use what's called camelCase. The first word is lowercase, and the first letter of every following word is uppercase.
+
+# --hints--
+
+You should use `var` to declare a variable called `currentWeapon`.
+
+```js
+assert.match(code, /var currentweapon/i);
+```
+
+You should use camelCase to name your variable.
+
+```js
+assert.match(code, /currentWeapon/);
+```
+
+Your `currentWeapon` variable should be set to `0`.
+
+```js
+assert.equal(currentWeapon, 0);
+```
+
+You should initialize your variable to `0`.
+
+```js
+assert.match(code, /var currentWeapon\s?=\s?0/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+--fcc-editable-region--
+var xp = 0;
+var health = 100;
+var gold = 50;
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b365f1cdeb33efc2502e.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b365f1cdeb33efc2502e.md
new file mode 100644
index 00000000000..63ecefac153
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b365f1cdeb33efc2502e.md
@@ -0,0 +1,138 @@
+---
+id: 62a3b365f1cdeb33efc2502e
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+You have been declaring your variables with the `var` keyword. However, in modern JavaScript it is best practice to use the `let` keyword instead. This fixes several unusual behaviors with `var` that can make your code difficult to debug.
+
+Change all of your `var` keywords to `let`.
+
+# --hints--
+
+You should not have any `var` keywords in your code.
+
+```js
+assert.notMatch(code, /var/);
+```
+
+You should use the `let` keyword to declare your `xp` variable.
+
+```js
+assert.match(code, /let xp/);
+```
+
+You should use the `let` keyword to declare your `health` variable.
+
+```js
+assert.match(code, /let health/);
+```
+
+You should use the `let` keyword to declare your `gold` variable.
+
+```js
+assert.match(code, /let gold/);
+```
+
+You should use the `let` keyword to declare your `currentWeapon` variable.
+
+```js
+assert.match(code, /let currentWeapon/);
+```
+
+You should not change the values of your variables.
+
+```js
+assert.equal(xp, 0);
+assert.equal(health, 100);
+assert.equal(gold, 50);
+assert.equal(currentWeapon, 0);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+--fcc-editable-region--
+var xp = 0;
+var health = 100;
+var gold = 50;
+var currentWeapon = 0;
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b3eab50e193608c19fc6.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b3eab50e193608c19fc6.md
new file mode 100644
index 00000000000..f4a27916dea
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b3eab50e193608c19fc6.md
@@ -0,0 +1,115 @@
+---
+id: 62a3b3eab50e193608c19fc6
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Using the `let` keyword, declare a variable called `fighting` but do not initialize it with a value. Remember to end your line with a semi-colon.
+
+# --hints--
+
+You should use `let` to declare a variable `fighting`.
+
+```js
+assert.match(code, /let fighting/);
+```
+
+Your `fighting` variable should not have a value.
+
+```js
+assert.isUndefined(fighting);
+```
+
+You should not assign a value to your `fighting` variable. Don't forget the semi-colon at the end of the line.
+
+```js
+assert.match(code, /let fighting;/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+--fcc-editable-region--
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b41c9494f937560640ab.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b41c9494f937560640ab.md
new file mode 100644
index 00000000000..c679c2cb1fe
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b41c9494f937560640ab.md
@@ -0,0 +1,140 @@
+---
+id: 62a3b41c9494f937560640ab
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+Declare two more variables named `monsterHealth` and `inventory`, but do not initialize them.
+
+# --hints--
+
+You should use `let` to declare your `monsterHealth` variable.
+
+```js
+assert.match(code, /let monsterHealth/i);
+```
+
+You should use camelCase to name your `monsterHealth` variable.
+
+```js
+assert.match(code, /monsterHealth/);
+```
+
+`monsterHealth` should not have a value.
+
+```js
+assert.isUndefined(monsterHealth);
+```
+
+You should not assign a value to your `monsterHealth` variable. Remember your semi-colon.
+
+```js
+assert.match(code, /let monsterHealth;/);
+```
+
+You should use `let` to declare your `inventory` variable.
+
+```js
+assert.match(code, /let inventory/i);
+```
+
+`inventory` should not have a value.
+
+```js
+assert.isUndefined(inventory);
+```
+
+You should not assign a value to your `inventory` variable. Remember your semi-colon.
+
+```js
+assert.match(code, /let inventory;/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+--fcc-editable-region--
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b49686792938718b90d3.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b49686792938718b90d3.md
new file mode 100644
index 00000000000..878b7879e25
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b49686792938718b90d3.md
@@ -0,0 +1,118 @@
+---
+id: 62a3b49686792938718b90d3
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+The variables you have assigned have all had values that are numbers. JavaScript has multiple different data types. The next one you will use is the string. Strings are used to store things like words or text. Strings are surrounded with double quotes, single quotes, or backticks. Here is an example of declaring a variable with a string:
+
+```js
+let developer = "Naomi";
+```
+
+Assign the `inventory` variable to have the value of `stick`.
+
+# --hints--
+
+You should set `inventory` to the string `stick`.
+
+```js
+assert.equal(inventory, "stick");
+```
+
+You should initialize your `inventory` variable with the string `stick`.
+
+```js
+assert.match(code, /let\s+inventory\s*=\s*('|"|`)stick\1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+--fcc-editable-region--
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory;
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b506dbaead396f58a701.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b506dbaead396f58a701.md
new file mode 100644
index 00000000000..bb8a09862a3
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b506dbaead396f58a701.md
@@ -0,0 +1,142 @@
+---
+id: 62a3b506dbaead396f58a701
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+The player's inventory in your game will be able to hold multiple items. You will need to use a data type that can do this. An array can be used to hold multiple values. For example:
+
+```js
+let order = ["first", "second", "third"];
+```
+
+This is an array which holds three values. Notice how the values are separated by commas. Change your `inventory` variable to be an array with the strings `stick`, `dagger`, and `sword`.
+
+# --hints--
+
+Your `inventory` variable should be an array.
+
+```js
+assert.isArray(inventory);
+```
+
+Your `inventory` variable should have three values.
+
+```js
+assert.lengthOf(inventory, 3);
+```
+
+Your `inventory` variable should include the string `stick`.
+
+```js
+assert.include(inventory, "stick");
+```
+
+Your `inventory` variable should include the string `dagger`.
+
+```js
+assert.include(inventory, "dagger");
+```
+
+Your `inventory` variable should include the string `sword`.
+
+```js
+assert.include(inventory, "sword");
+```
+
+Your `inventory` variable should have the values in the correct order.
+
+```js
+assert.deepEqual(inventory, ["stick", "dagger", "sword"]);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+--fcc-editable-region--
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = "stick";
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b5843544ce3a77459c27.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b5843544ce3a77459c27.md
new file mode 100644
index 00000000000..f7a00ecb775
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b5843544ce3a77459c27.md
@@ -0,0 +1,118 @@
+---
+id: 62a3b5843544ce3a77459c27
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+For now, you want the player to start with just the `stick`. Change the `inventory` array to have `stick` as its only value.
+
+# --hints--
+
+Your `inventory` variable should still be an array.
+
+```js
+assert.isArray(inventory);
+```
+
+Your `inventory` variable should only have one value.
+
+```js
+assert.lengthOf(inventory, 1);
+```
+
+Your `inventory` variable should include the string `stick`.
+
+```js
+assert.include(inventory, "stick");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+--fcc-editable-region--
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick", "dagger", "sword"];
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b79d520a7f3d0e25afd6.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b79d520a7f3d0e25afd6.md
new file mode 100644
index 00000000000..af9e9e6bf70
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3b79d520a7f3d0e25afd6.md
@@ -0,0 +1,128 @@
+---
+id: 62a3b79d520a7f3d0e25afd6
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+JavaScript interacts with the HTML using the Document Object Model, or DOM. The DOM is a tree of objects that represents the HTML. You can access the HTML using the `document` variable, which represents your entire HTML document.
+
+One method for finding specific elements in your HTML is using the `querySelector()` method. The `querySelector()` method takes a CSS selector as an argument and returns the first element that matches that selector. For example, to find the `
` element in your HTML, you would write:
+
+```js
+let h1 = document.querySelector("h1");
+```
+
+Note that `h1` is a string and matches the CSS selector you would use. Create a `button1` variable and use `querySelector()` to assign it your element with the `id` of `button1`. Remember that CSS `id` selectors are prefixed with a `#`.
+
+# --hints--
+
+You should use `let` to declare a `button1` variable.
+
+```js
+assert.match(code, /let button1/);
+```
+
+You should use `document.querySelector()`.
+
+```js
+assert.match(code, /document\.querySelector/);
+```
+
+You should use the `#button1` selector.
+
+```js
+assert.match(code, /querySelector\(('|")#button1\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3bb9aeefe4b3fc43c6d7b.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3bb9aeefe4b3fc43c6d7b.md
new file mode 100644
index 00000000000..0e0eaee9ae7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3bb9aeefe4b3fc43c6d7b.md
@@ -0,0 +1,116 @@
+---
+id: 62a3bb9aeefe4b3fc43c6d7b
+title: Step 31
+challengeType: 0
+dashedName: step-31
+---
+
+# --description--
+
+`button1` is a variable that is not going to be reassigned. If you are not going to assign a new value to a variable, it is best practice to use the `const` keyword to declare it instead of the `let` keyword. This will tell JavaScript to throw an error if you accidentally reassign it.
+
+Change your `button1` variable to be declared with the `const` keyword.
+
+# --hints--
+
+Your `button1` variable should be declared with `const`.
+
+```js
+assert.match(code, /const button1/);
+```
+
+Your `button1` variable should still have the value of your `#button1` element.
+
+```js
+assert.deepEqual(button1, document.querySelector("#button1"));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+--fcc-editable-region--
+let button1 = document.querySelector("#button1");
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3bec30ea7f941412512dc.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3bec30ea7f941412512dc.md
new file mode 100644
index 00000000000..065f7587076
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3bec30ea7f941412512dc.md
@@ -0,0 +1,181 @@
+---
+id: 62a3bec30ea7f941412512dc
+title: Step 33
+challengeType: 0
+dashedName: step-33
+---
+
+# --description--
+
+Just like you did with the buttons, create variables for the following `id`s and use `querySelector()` to give them the element as a value:
+
+`text`, `xpText`, `healthText`, `goldText`, `monsterStats`, and `monsterName`.
+
+Remember to declare these with the `const` keyword, and name the variables to match the `id`s.
+
+# --hints--
+
+You should declare a `text` variable with `const`.
+
+```js
+assert.match(code, /const text/);
+```
+
+Your `text` variable should have the value of your `#text` element.
+
+```js
+assert.deepEqual(text, document.querySelector('#text'));
+```
+
+You should declare a `xpText` variable with `const`.
+
+```js
+assert.match(code, /const xpText/);
+```
+
+Your `xpText` variable should have the value of your `#xpText` element.
+
+```js
+assert.deepEqual(xpText, document.querySelector('#xpText'));
+```
+
+You should declare a `healthText` variable with `const`.
+
+```js
+assert.match(code, /const healthText/);
+```
+
+Your `healthText` variable should have the value of your `#healthText` element.
+
+```js
+assert.deepEqual(healthText, document.querySelector('#healthText'));
+```
+
+You should declare a `goldText` variable with `const`.
+
+```js
+assert.match(code, /const goldText/);
+```
+
+Your `goldText` variable should have the value of your `#goldText` element.
+
+```js
+assert.deepEqual(goldText, document.querySelector('#goldText'));
+```
+
+You should declare a `monsterStats` variable with `const`.
+
+```js
+assert.match(code, /const monsterStats/);
+```
+
+Your `monsterStats` variable should have the value of your `#monsterStats` element.
+
+```js
+assert.deepEqual(monsterStats, document.querySelector('#monsterStats'));
+```
+
+You should declare a `monsterName` variable with `const`.
+
+```js
+assert.match(code, /const monsterName/);
+```
+
+Your `monsterName` variable should have the value of your `#monsterName` element.
+
+```js
+assert.deepEqual(monsterName, document.querySelector('#monsterName'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+--fcc-editable-region--
+const button1 = document.querySelector("#button1");
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c0ab883fd9435cd5c518.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c0ab883fd9435cd5c518.md
new file mode 100644
index 00000000000..ed392fd2cc4
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c0ab883fd9435cd5c518.md
@@ -0,0 +1,134 @@
+---
+id: 62a3c0ab883fd9435cd5c518
+title: Step 35
+challengeType: 0
+dashedName: step-35
+---
+
+# --description--
+
+Comments allow you to add notes to your code. In JavaScript, single-line comments can be written with `//` and multi-line comments can be written with `/*` and `*/`. For example, here are single and multi-line comments that say "Hello World":
+
+```js
+// hello world
+/*
+ hello world
+*/
+```
+
+Add a single-line comment that says `initialize buttons`.
+
+# --hints--
+
+You should use the `//` symbol to start a single-line comment.
+
+```js
+assert.match(code, /\/\//);
+```
+
+Your comment should have the text `initialize buttons`.
+
+```js
+assert.match(code, /\/\/\s*initialize buttons/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c2fccf186146b59c6e96.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c2fccf186146b59c6e96.md
new file mode 100644
index 00000000000..0f2fe813e63
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c2fccf186146b59c6e96.md
@@ -0,0 +1,134 @@
+---
+id: 62a3c2fccf186146b59c6e96
+title: Step 36
+challengeType: 0
+dashedName: step-36
+---
+
+# --description--
+
+`button1` represents your first `button` element. These elements have a special property called `onclick`, which you can use to determine what happens when someone clicks that button. Properties in JavaScript can be accessed in a couple of ways - the first is with dot notation. Accessing the `onclick` property of a button would look like `button.onclick`.
+
+Use dot notation to set the `onclick` property of your `button1` to the variable `goStore`. This variable will be something you write later. Note that `button1` is already declared, so you do not need to use `let` or `const`.
+
+# --hints--
+
+You should use dot notation to access the `onclick` property of `button1`.
+
+```js
+assert.match(code, /button1\.onclick/);
+```
+
+You should not use `let` or `const`.
+
+```js
+assert.notMatch(code, /(let|const)\s+button1\.onclick/);
+```
+
+You should set the `onclick` property of `button1` to the variable `goStore`.
+
+```js
+assert.match(code, /button1\.onclick\s*=\s*goStore/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+--fcc-editable-region--
+// initialize buttons
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c4a0e52767482c5202d4.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c4a0e52767482c5202d4.md
new file mode 100644
index 00000000000..73d0dc234d9
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c4a0e52767482c5202d4.md
@@ -0,0 +1,151 @@
+---
+id: 62a3c4a0e52767482c5202d4
+title: Step 37
+challengeType: 0
+dashedName: step-37
+---
+
+# --description--
+
+Using the same syntax, set the `onclick` properties of `button2` and `button3` to `goCave` and `fightDragon` respectively.
+
+# --hints--
+
+You should use dot notation to access the `onclick` property of `button2`.
+
+```js
+assert.match(code, /button2\.onclick/);
+```
+
+You should not use `let` or `const` to assign `button2.onclick`.
+
+```js
+assert.notMatch(code, /(let|const)\s+button2\.onclick/);
+```
+
+You should set the `onclick` property of `button2` to the variable `goCave`.
+
+```js
+assert.match(code, /button2\.onclick\s*=\s*goCave/);
+```
+
+You should use dot notation to access the `onclick` property of `button3`.
+
+```js
+assert.match(code, /button3\.onclick/);
+```
+
+You should not use `let` or `const` to assign `button3.onclick`.
+
+```js
+assert.notMatch(code, /(let|const)\s+button3\.onclick/);
+```
+
+You should set the `onclick` property of `button3` to the variable `fightDragon`.
+
+```js
+assert.match(code, /button3\.onclick\s*=\s*fightDragon/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+--fcc-editable-region--
+// initialize buttons
+button1.onclick = goStore;
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c668afc43b4a134cca81.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c668afc43b4a134cca81.md
new file mode 100644
index 00000000000..38a51618160
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c668afc43b4a134cca81.md
@@ -0,0 +1,150 @@
+---
+id: 62a3c668afc43b4a134cca81
+title: Step 38
+challengeType: 0
+dashedName: step-38
+---
+
+# --description--
+
+Functions are special tools that allow you to run sections of code at specific times. You can declare functions using the `function` keyword. Here is an example of a function called `functionName` - note the opening and closing curly braces. These indicate the section of code that is within the function.
+
+```js
+function functionName() {
+
+}
+```
+
+Create an empty function named `goStore`. This will match the `goStore` variable you used earlier.
+
+# --hints--
+
+You should declare `goStore` with the `function` keyword.
+
+```js
+assert.match(code, /function\s*goStore()/);
+```
+
+`goStore` should be defined.
+
+```js
+assert.isDefined(goStore);
+```
+
+`goStore` should be a function.
+
+```js
+assert.isFunction(goStore);
+```
+
+`goStore` should be an empty function.
+
+```js
+assert.equal(goStore.toString(), "function goStore() {}");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c8bf3980c14c438d2aed.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c8bf3980c14c438d2aed.md
new file mode 100644
index 00000000000..7bec654ec15
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c8bf3980c14c438d2aed.md
@@ -0,0 +1,138 @@
+---
+id: 62a3c8bf3980c14c438d2aed
+title: Step 39
+challengeType: 0
+dashedName: step-39
+---
+
+# --description--
+
+For now, make your `goStore` function output the message `Going to store.` to the console. For example, here is a function that outputs the message "Hello World".
+
+```js
+function functionName() {
+ console.log("Hello World");
+}
+```
+
+# --hints--
+
+You should have a `console.log("Going to store.");` line in your code. Don't forget the semi-colon.
+
+```js
+assert.match(code, /console\.log\(('|")Going to store\.\1\);/);
+```
+
+Your `console.log("Going to store.");` line should be in your `goStore` function.
+
+```js
+assert.match(goStore.toString(), /console\.log\(('|")Going to store\.\1\);/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function goStore() {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c91a2bab1b4d6fabb726.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c91a2bab1b4d6fabb726.md
new file mode 100644
index 00000000000..a911182a57c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3c91a2bab1b4d6fabb726.md
@@ -0,0 +1,146 @@
+---
+id: 62a3c91a2bab1b4d6fabb726
+title: Step 40
+challengeType: 0
+dashedName: step-40
+---
+
+# --description--
+
+Now create a `goCave` function that prints `Going to cave.` to the console.
+
+# --hints--
+
+You should use the `function` keyword to declare `goCave`.
+
+```js
+assert.match(code, /function goCave/);
+```
+
+`goCave` should be a function.
+
+```js
+assert.isFunction(goCave);
+```
+
+You should have a `console.log("Going to cave.");` line in your code.
+
+```js
+assert.match(code, /console.log\(('|")Going to cave\.\1\)/);
+```
+
+Your `console.log("Going to cave.");` line should be inside your `goCave` function.
+
+```js
+assert.match(goCave.toString(), /console.log\(('|")Going to cave\.\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function goStore() {
+ console.log("Going to store.");
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3cdb11478a34ff4a6470d.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3cdb11478a34ff4a6470d.md
new file mode 100644
index 00000000000..c14f5a7d858
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3cdb11478a34ff4a6470d.md
@@ -0,0 +1,152 @@
+---
+id: 62a3cdb11478a34ff4a6470d
+title: Step 41
+challengeType: 0
+dashedName: step-41
+---
+
+# --description--
+
+Now create a `fightDragon` function that prints `Fighting dragon.` to the console.
+
+Once you have done that, open your console and try clicking the buttons on your project.
+
+# --hints--
+
+You should use the `function` keyword to declare `fightDragon`.
+
+```js
+assert.match(code, /function fightDragon/);
+```
+
+`fightDragon` should be a function.
+
+```js
+assert.isFunction(fightDragon);
+```
+
+You should have a `console.log("Fighting dragon.");` line in your code.
+
+```js
+assert.match(code, /console.log\(('|")Fighting dragon\.\1\)/);
+```
+
+Your `console.log("Fighting dragon.");` line should be inside your `fightDragon` function.
+
+```js
+assert.match(fightDragon.toString(), /console.log\(('|")Fighting dragon\.\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function goStore() {
+ console.log("Going to store.");
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3cfc8328d3351b95d4f61.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3cfc8328d3351b95d4f61.md
new file mode 100644
index 00000000000..490ea3e8e2f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a3cfc8328d3351b95d4f61.md
@@ -0,0 +1,164 @@
+---
+id: 62a3cfc8328d3351b95d4f61
+title: Step 42
+challengeType: 0
+dashedName: step-42
+---
+
+# --description--
+
+The `innerText` property controls the text that appears in an HTML element. For example:
+
+```js
+const info = document.querySelector("#info");
+info.innerText = "Hello World";
+```
+
+This code would change the element assigned to the `div` variable to have the text `Hello World`.
+
+When a player clicks your `Go to store` button, you want to change the buttons and text. Remove the code inside the `goStore` function and add a line that updates the text of `button1` to say `Buy 10 health (10 gold)`.
+
+# --hints--
+
+You should not have a `console.log("Going to store.");` line in your code.
+
+```js
+assert.notMatch(code, /console.log\(('|")Going to store\.\1\)/);
+```
+
+You should use dot notation to access the `innerText` property of `button1`.
+
+```js
+assert.match(code, /button1\.innerText/);
+```
+
+You should not use `let` or `const` to access the `innerText` property of `button1`.
+
+```js
+assert.notMatch(code, /(let|const)\s+button1.innerText/);
+```
+
+You should update the `innerText` property of `button1` to be `Buy 10 health (10 gold)`.
+
+```js
+assert.match(code, /button1\.innerText\s*=\s*('|")Buy 10 health \(10 gold\)\1/);
+```
+
+You should update the `innerText` property within your `goStore` function.
+
+```js
+assert.match(goStore.toString(), /button1\.innerText\s*=\s*('|")Buy 10 health \(10 gold\)\1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ border: 1px solid black;
+ padding: 5px;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function goStore() {
+ console.log("Going to store.");
+}
+--fcc-editable-region--
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7beb1ad61211ac153707f.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7beb1ad61211ac153707f.md
new file mode 100644
index 00000000000..8d5c8d1245f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7beb1ad61211ac153707f.md
@@ -0,0 +1,176 @@
+---
+id: 62a7beb1ad61211ac153707f
+title: Step 43
+challengeType: 0
+dashedName: step-43
+---
+
+# --description--
+
+Now add a line that updates the text of `button2` to say `Buy weapon (30 gold)` and update the text of `button3` to say `Go to town square`.
+
+# --hints--
+
+You should use dot notation to access the `innerText` property of `button2`.
+
+```js
+assert.match(code, /button2\.innerText/);
+```
+
+You should not use `let` or `const` to access the `innerText` property of `button2`.
+
+```js
+assert.notMatch(code, /(let|const)\s+button2.innerText/);
+```
+
+You should update the `innerText` property of `button2` to be `Buy weapon (30 gold)`.
+
+```js
+assert.match(code, /button2\.innerText\s*=\s*('|")Buy weapon \(30 gold\)\1/);
+```
+
+You should update the `innerText` property within your `goStore` function.
+
+```js
+assert.match(goStore.toString(), /button2\.innerText\s*=\s*('|")Buy weapon \(30 gold\)\1/);
+```
+
+You should use dot notation to access the `innerText` property of `button3`.
+
+```js
+assert.match(code, /button3\.innerText/);
+```
+
+You should not use `let` or `const` to access the `innerText` property of `button3`.
+
+```js
+assert.notMatch(code, /(let|const)\s+button3.innerText/);
+```
+
+You should update the `innerText` property of `button3` to be `Go to town square`.
+
+```js
+assert.match(code, /button3\.innerText\s*=\s*('|")Go to town square\1/);
+```
+
+You should update the `innerText` property within your `goStore` function.
+
+```js
+assert.match(goStore.toString(), /button3\.innerText\s*=\s*('|")Go to town square\1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+}
+--fcc-editable-region--
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7bf06d2ad9d1c5024e833.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7bf06d2ad9d1c5024e833.md
new file mode 100644
index 00000000000..981e39344f7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7bf06d2ad9d1c5024e833.md
@@ -0,0 +1,202 @@
+---
+id: 62a7bf06d2ad9d1c5024e833
+title: Step 44
+challengeType: 0
+dashedName: step-44
+---
+
+# --description--
+
+You will also need to update the functions that run when the buttons are clicked. Update the `onclick` property for each button to run `buyHealth`, `buyWeapon`, and `goTown`, respectively.
+
+# --hints--
+
+You should use dot notation to access the `onclick` property of `button1`.
+
+```js
+assert.match(code, /button1\.onclick/);
+```
+
+You should not use `let` or `const` to access the `onclick` property of `button1`.
+
+```js
+assert.notMatch(code, /(let|const)\s+button1.onclick/);
+```
+
+You should set the `onclick` property of `button1` to be `buyHealth`.
+
+```js
+assert.match(code, /button1\.onclick\s*=\s*buyHealth/);
+```
+
+You should set the `onclick` property of `button1` in your `goStore` function.
+
+```js
+assert.match(goStore.toString(), /button1\.onclick\s*=\s*buyHealth/);
+```
+
+You should use dot notation to access the `onclick` property of `button2`.
+
+```js
+assert.match(code, /button2\.onclick/);
+```
+
+You should not use `let` or `const` to access the `onclick` property of `button2`.
+
+```js
+assert.notMatch(code, /(let|const)\s+button2.onclick/);
+```
+
+You should set the `onclick` property of `button2` to be `buyWeapon`.
+
+```js
+assert.match(code, /button2\.onclick\s*=\s*buyWeapon/);
+```
+
+You should set the `onclick` property of `button2` in your `goStore` function.
+
+```js
+assert.match(goStore.toString(), /button2\.onclick\s*=\s*buyWeapon/);
+```
+
+You should use dot notation to access the `onclick` property of `button3`.
+
+```js
+assert.match(code, /button3\.onclick/);
+```
+
+You should not use `let` or `const` to access the `onclick` property of `button3`.
+
+```js
+assert.notMatch(code, /(let|const)\s+button3.onclick/);
+```
+
+You should set the `onclick` property of `button3` to be `goTown`.
+
+```js
+assert.match(code, /button3\.onclick\s*=\s*goTown/);
+```
+
+You should set the `onclick` property of `button3` in your `goStore` function.
+
+```js
+assert.match(goStore.toString(), /button3\.onclick\s*=\s*goTown/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+}
+--fcc-editable-region--
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7bfabe119461eb13ccbd6.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7bfabe119461eb13ccbd6.md
new file mode 100644
index 00000000000..eed48a208c4
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7bfabe119461eb13ccbd6.md
@@ -0,0 +1,157 @@
+---
+id: 62a7bfabe119461eb13ccbd6
+title: Step 45
+challengeType: 0
+dashedName: step-45
+---
+
+# --description--
+
+Now you need to modify your display text. Change the `innerText` of the `text` to be `You enter the store.`.
+
+# --hints--
+
+You should use dot notation to access the `innerText` property of `text`.
+
+```js
+assert.match(code, /text\.innerText/);
+```
+
+You should not use `let` or `const` to access the `innerText` property of `text`.
+
+```js
+assert.notMatch(code, /(let|const)\s+text.innerText/);
+```
+
+You should update the `innerText` property of `text` to be `You enter the store.`.
+
+```js
+assert.match(code, /text\.innerText\s*=\s*('|")You enter the store.\1/);
+```
+
+You should update the `innerText` property within your `goStore` function.
+
+```js
+assert.match(goStore.toString(), /text\.innerText\s*=\s*('|")You enter the store.\1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+--fcc-editable-region--
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+
+function goTown() {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7c071219da921758a35bb.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7c071219da921758a35bb.md
new file mode 100644
index 00000000000..20ac473611a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7c071219da921758a35bb.md
@@ -0,0 +1,194 @@
+---
+id: 62a7c071219da921758a35bb
+title: Step 48
+challengeType: 0
+dashedName: step-48
+---
+
+# --description--
+
+In your `goTown` function, update your button `innerText` properties to be `Go to store`, `Go to cave`, and `Fight dragon`. Update your `onclick` properties to be `goStore`, `goCave`, and `fightDragon`, respectively. Finally, update your text's `innerText` property to be `You are in the town square. You see a sign that says Store.`.
+
+# --hints--
+
+You should set the `button1.innerText` property to be `Go to store` in your `goTown` function.
+
+```js
+assert.match(goTown.toString(), /button1\.innerText\s*=\s*('|")Go to store\1/);
+```
+
+You should set the `button2.innerText` property to be `Go to cave` in your `goTown` function.
+
+```js
+assert.match(goTown.toString(), /button2\.innerText\s*=\s*('|")Go to cave\1/);
+```
+
+You should set the `button3.innerText` property to be `Fight dragon` in your `goTown` function.
+
+```js
+assert.match(goTown.toString(), /button3\.innerText\s*=\s*('|")Fight dragon\1/);
+```
+
+You should set the `button1.onclick` property to be `goStore` in your `goTown` function.
+
+```js
+assert.match(goTown.toString(), /button1\.onclick\s*=\s*goStore/);
+```
+
+You should set the `button2.onclick` property to be `goCave` in your `goTown` function.
+
+```js
+assert.match(goTown.toString(), /button2\.onclick\s*=\s*goCave/);
+```
+
+You should set the `button3.onclick` property to be `fightDragon` in your `goTown` function.
+
+```js
+assert.match(goTown.toString(), /button3\.onclick\s*=\s*fightDragon/);
+```
+
+You should set the `text.innerText` property to be `You are in the town square. You see a sign that says Store.` in your `goTown` function.
+
+```js
+assert.match(goTown.toString(), /text\.innerText\s*=\s*('|")You are in the town square. You see a sign that says Store\.\1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function goTown() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+--fcc-editable-region--
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7c23e6b511f22ed71197a.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7c23e6b511f22ed71197a.md
new file mode 100644
index 00000000000..6b26d69619b
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7c23e6b511f22ed71197a.md
@@ -0,0 +1,164 @@
+---
+id: 62a7c23e6b511f22ed71197a
+title: Step 49
+challengeType: 0
+dashedName: step-49
+---
+
+# --description--
+
+You need to wrap the text `Store` in double quotes. Because your string is already wrapped in double quotes, you'll need to escape the quotes around `Store`. You can escape them with a backslash `\`. Here is an example:
+
+```js
+const escapedString = "Naomi likes to play \"Zelda\" sometimes.";
+```
+
+Wrap the text `Store` in double quotes within your `text.innerText` line.
+
+# --hints--
+
+You should wrap the text `Store` in double quotes.
+
+```js
+assert.match(goTown.toString(), /text\.innerText\s*=\s*"You are in the town square. You see a sign that says \\"Store\\"."/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function goTown() {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says Store.";
+}
+--fcc-editable-region--
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7cc99577fbf25ee7a7d76.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7cc99577fbf25ee7a7d76.md
new file mode 100644
index 00000000000..82ae722f3d8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a7cc99577fbf25ee7a7d76.md
@@ -0,0 +1,180 @@
+---
+id: 62a7cc99577fbf25ee7a7d76
+title: Step 50
+challengeType: 0
+dashedName: step-50
+---
+
+# --description--
+
+You have repetition in the `goTown` and `goStore` functions. When you have repetition in your code, this is a sign that you need another function. Functions can take parameters, which are values that are given to the function each time it is run. Here is a function that takes a parameter called `param`:
+
+```js
+function myFunction(param) {
+ console.log(param);
+}
+```
+
+Create an empty `update` function that takes a parameter called `location`.
+
+# --hints--
+
+You should use the `function` keyword to declare `update`.
+
+```js
+assert.match(code, /function\s+update/);
+```
+
+Your `update` function should take a parameter called `location`.
+
+```js
+assert.match(update.toString(), /update\(location\)/);
+```
+
+Your `update` function should be empty.
+
+```js
+assert.equal(update.toString(), function update(location) {});
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+
+}
+
+function goTown() {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8a9d876b2580943ba9351.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8a9d876b2580943ba9351.md
new file mode 100644
index 00000000000..4f9143c205b
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8a9d876b2580943ba9351.md
@@ -0,0 +1,171 @@
+---
+id: 62a8a9d876b2580943ba9351
+title: Step 52
+challengeType: 0
+dashedName: step-52
+---
+
+# --description--
+
+You previously used an array to store strings. But arrays can store any data type. This time, your array will be storing objects. Objects are similar to arrays, but with a few differences. One difference is that objects use properties, or keys, to access and modify data.
+
+Objects are indicated by curly braces. An empty object would look like `{}`. Add an empty object to your `locations` array.
+
+# --hints--
+
+Your first value of `locations` should be an object.
+
+```js
+assert.isObject(locations[0]);
+```
+
+Your first value of `locations` should be an empty object.
+
+```js
+assert.deepEqual(locations[0], {});
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+--fcc-editable-region--
+const locations = [];
+--fcc-editable-region--
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+
+}
+
+function goTown() {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8aa98a8289d0a698eee1d.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8aa98a8289d0a698eee1d.md
new file mode 100644
index 00000000000..d5c3664e5ed
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8aa98a8289d0a698eee1d.md
@@ -0,0 +1,187 @@
+---
+id: 62a8aa98a8289d0a698eee1d
+title: Step 53
+challengeType: 0
+dashedName: step-53
+---
+
+# --description--
+
+Object properties are written as `key: value` pairs, where `key` is the name of the property (or the key), and `value` is the value that property holds. For example, here is an object with a key of `name` set to `Quincy Larson`.
+
+```js
+{
+ name: "Quincy Larson"
+}
+```
+
+Add a `name` property to your empty object and give it a value of `town square`.
+
+# --hints--
+
+Your first value of `locations` should be an object.
+
+```js
+assert.isObject(locations[0]);
+```
+
+Your first value of `locations` should have a `name` property.
+
+```js
+assert.isDefined(locations[0].name);
+```
+
+Your first value of `locations` should have a `name` property with a value of `town square`.
+
+```js
+assert.equal(locations[0].name, "town square");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+--fcc-editable-region--
+const locations = [
+ {
+
+ }
+];
+--fcc-editable-region--
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+
+}
+
+function goTown() {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ab0e27cbaf0b54ba8a42.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ab0e27cbaf0b54ba8a42.md
new file mode 100644
index 00000000000..45578691077
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ab0e27cbaf0b54ba8a42.md
@@ -0,0 +1,200 @@
+---
+id: 62a8ab0e27cbaf0b54ba8a42
+title: Step 54
+challengeType: 0
+dashedName: step-54
+---
+
+# --description--
+
+Just like array values, object properties are separated by a comma. Add a comma after your `name` property and add a `button text` property with the value of an empty array. Note that because the property name has more than one word, you'll need to surround it in quotes.
+
+For example:
+
+```js
+{
+ name: "Naomi",
+ "favorite color": "purple"
+}
+```
+
+# --hints--
+
+Your first `locations` value should be an object.
+
+```js
+assert.isObject(locations[0]);
+```
+
+Your first `locations` value should have a `button text` property.
+
+```js
+assert.isDefined(locations[0]["button text"]);
+```
+
+Your first `locations` value should have a `button text` property with a value that is an array.
+
+```js
+assert.isArray(locations[0]["button text"]);
+```
+
+Your first `locations` value should have a `button text` property with a value that is an empty array.
+
+```js
+assert.equal(locations[0]["button text"].length, 0);
+```
+
+You should not remove or change the `name` property.
+
+```js
+assert.equal(locations[0].name, "town square");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+--fcc-editable-region--
+const locations = [
+ {
+ name: "town square"
+ }
+];
+--fcc-editable-region--
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+
+}
+
+function goTown() {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ac194679e60cb561b0a8.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ac194679e60cb561b0a8.md
new file mode 100644
index 00000000000..5a1412cf312
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ac194679e60cb561b0a8.md
@@ -0,0 +1,194 @@
+---
+id: 62a8ac194679e60cb561b0a8
+title: Step 55
+challengeType: 0
+dashedName: step-55
+---
+
+# --description--
+
+Give your empty `button text` array three string elements. Use the three strings being assigned to the button `innerText` properties in the `goTown` function. Remember that array values are separated by commas.
+
+# --hints--
+
+Your `button text` array should have three elements.
+
+```js
+assert.lengthOf(locations[0]["button text"], 3);
+```
+
+Your `button text` array should have three strings.
+
+```js
+assert.isString(locations[0]["button text"][0]);
+assert.isString(locations[0]["button text"][1]);
+assert.isString(locations[0]["button text"][2]);
+```
+
+The first value in the `button text` array should be "Go to store".
+
+```js
+assert.equal(locations[0]["button text"][0], "Go to store");
+```
+
+The second value in the `button text` array should be "Go to cave".
+
+```js
+assert.equal(locations[0]["button text"][1], "Go to cave");
+```
+
+The third value in the `button text` array should be "Fight dragon".
+
+```js
+assert.equal(locations[0]["button text"][2], "Fight dragon");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+--fcc-editable-region--
+const locations = [
+ {
+ name: "town square",
+ "button text": []
+ }
+];
+--fcc-editable-region--
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+
+}
+
+function goTown() {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ad8e01d7cb0deae5ec66.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ad8e01d7cb0deae5ec66.md
new file mode 100644
index 00000000000..1229366bb3a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ad8e01d7cb0deae5ec66.md
@@ -0,0 +1,198 @@
+---
+id: 62a8ad8e01d7cb0deae5ec66
+title: Step 56
+challengeType: 0
+dashedName: step-56
+---
+
+# --description--
+
+Create another property in your object called `button functions`. Give this property an array containing the three functions assigned to the `onclick` properties in the `goTown` function. Remember that these functions are variables, not strings, and should not be wrapped in quotes.
+
+# --hints--
+
+Your first `locations` object should have a `button functions` property.
+
+```js
+assert.isDefined(locations[0]["button functions"]);
+```
+
+Your `button functions` property should be an array.
+
+```js
+assert.isArray(locations[0]["button functions"]);
+```
+
+Your `button functions` property should have three values in it.
+
+```js
+assert.lengthOf(locations[0]["button functions"], 3);
+```
+
+Your first `button functions` array value should be the function `goStore`.
+
+```js
+assert.equal(locations[0]["button functions"][0], goStore);
+```
+
+Your second `button functions` array value should be the function `goCave`.
+
+```js
+assert.equal(locations[0]["button functions"][1], goCave);
+```
+
+Your third `button functions` array value should be the function `fightDragon`.
+
+```js
+assert.equal(locations[0]["button functions"][2], fightDragon);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+--fcc-editable-region--
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"]
+ }
+];
+--fcc-editable-region--
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+
+}
+
+function goTown() {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ade9b2f5b30ef0b606c2.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ade9b2f5b30ef0b606c2.md
new file mode 100644
index 00000000000..7ac20d72a3e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ade9b2f5b30ef0b606c2.md
@@ -0,0 +1,181 @@
+---
+id: 62a8ade9b2f5b30ef0b606c2
+title: Step 57
+challengeType: 0
+dashedName: step-57
+---
+
+# --description--
+
+Add one final property to the object named `text`. Give this property the final `text.innerText` value from the `goTown` function.
+
+# --hints--
+
+Your first `locations` value should have a `text` property.
+
+```js
+assert.isDefined(locations[0]["text"]);
+```
+
+Your `text` property should be a string.
+
+```js
+assert.isString(locations[0]["text"]);
+```
+
+Your `text` property should have the value `You are in the town square. You see a sign that says \"Store\".`
+
+```js
+assert.equal(locations[0]["text"], "You are in the town square. You see a sign that says \"Store\".");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+--fcc-editable-region--
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon]
+ }
+];
+--fcc-editable-region--
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+
+}
+
+function goTown() {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ae85fcaedc0fddc7ca4f.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ae85fcaedc0fddc7ca4f.md
new file mode 100644
index 00000000000..79d6d140e1e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ae85fcaedc0fddc7ca4f.md
@@ -0,0 +1,235 @@
+---
+id: 62a8ae85fcaedc0fddc7ca4f
+title: Step 58
+challengeType: 0
+dashedName: step-58
+---
+
+# --description--
+
+Add a second object to your `locations` array (remember to separate them with a comma). Following the pattern you used in the first object, create the same properties but use the values from the `goStore` function. Set the `name` property to `store`.
+
+# --hints--
+
+Your `locations` array should have two values.
+
+```js
+assert.lengthOf(locations, 2);
+```
+
+Both `locations` values should be objects.
+
+
+```js
+assert.isObject(locations[0]);
+assert.isObject(locations[1]);
+```
+
+Your second `locations` object should have a `name` property with the value of `store`.
+
+```js
+assert.equal(locations[1].name, "store");
+```
+
+Your second `locations` object should have a `button text` property which is an array.
+
+```js
+assert.isArray(locations[1]["button text"]);
+```
+
+Your `button text` property should have the string values `Buy 10 health (10 gold)`, `Buy weapon (30 gold)`, and `Go to town square`.
+
+```js
+assert.equal(locations[1]["button text"][0], "Buy 10 health (10 gold)");
+assert.equal(locations[1]["button text"][1], "Buy weapon (30 gold)");
+assert.equal(locations[1]["button text"][2], "Go to town square");
+```
+
+Your second `locations` object should have a `button functions` property which is an array.
+
+```js
+assert.isArray(locations[1]["button functions"]);
+```
+
+Your `button functions` property should have the function values `buyHealth`, `buyWeapon`, and `goTown`.
+
+```js
+assert.equal(locations[1]["button functions"][0], buyHealth);
+assert.equal(locations[1]["button functions"][1], buyWeapon);
+assert.equal(locations[1]["button functions"][2], goTown);
+```
+
+Your second `locations` object should have a `text` property which is a string.
+
+```js
+assert.isString(locations[1].text);
+```
+
+Your second `locations` object should have a `text` property with the value of `You enter the store.`.
+
+```js
+assert.equal(locations[1].text, "You enter the store.");
+```
+
+You should not modify the first `locations` object.
+
+```js
+assert.deepEqual(locations[0], {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+});
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+--fcc-editable-region--
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ }
+];
+--fcc-editable-region--
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+
+}
+
+function goTown() {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b0b5053f16111b0b6b5f.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b0b5053f16111b0b6b5f.md
new file mode 100644
index 00000000000..c60cf5907da
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b0b5053f16111b0b6b5f.md
@@ -0,0 +1,224 @@
+---
+id: 62a8b0b5053f16111b0b6b5f
+title: Step 59
+challengeType: 0
+dashedName: step-59
+---
+
+# --description--
+
+Now you can consolidate some of your code. Start by copying the code from inside the `goTown` function and paste it into your `update` function. Then, remove all the code from inside the `goTown` and `goStore` functions.
+
+# --hints--
+
+Your `update` function should set `button1.innerText` to `Go to store`.
+
+```js
+assert.match(update.toString(), /button1\.innerText\s*=\s*('|")Go to store\1/);
+```
+
+Your `update` function should set `button2.innerText` to `Go to cave`.
+
+```js
+assert.match(update.toString(), /button2\.innerText\s*=\s*('|")Go to cave\1/);
+```
+
+Your `update` function should set `button3.innerText` to `Fight dragon`.
+
+```js
+assert.match(update.toString(), /button3\.innerText\s*=\s*('|")Fight dragon\1/);
+```
+
+Your `update` function should set `button1.onclick` to `goStore`.
+
+```js
+assert.match(update.toString(), /button1\.onclick\s*=\s*goStore/);
+```
+
+Your `update` function should set `button2.onclick` to `goCave`.
+
+```js
+assert.match(update.toString(), /button2\.onclick\s*=\s*goCave/);
+```
+
+Your `update` function should set `button3.onclick` to `fightDragon`.
+
+```js
+assert.match(update.toString(), /button3\.onclick\s*=\s*fightDragon/);
+```
+
+Your `update` function should set `text.innerText` to `You are in the town square. You see a sign that says "Store".`.
+
+```js
+assert.match(update.toString(), /text\.innerText\s*=\s*"You are in the town square. You see a sign that says \\"Store\\"\."/);
+```
+
+Your `goTown` function should be empty.
+
+```js
+assert.match(goTown.toString(), /function goTown\(\) \{\}/);
+```
+
+Your `goStore` function should be empty.
+
+```js
+assert.match(goStore.toString(), /function goStore\(\) \{\}/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function update(location) {
+
+}
+
+function goTown() {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+function goStore() {
+ button1.innerText = "Buy 10 health (10 gold)";
+ button2.innerText = "Buy weapon (30 gold)";
+ button3.innerText = "Go to town square";
+ button1.onclick = buyHealth;
+ button2.onclick = buyWeapon;
+ button3.onclick = goTown;
+ text.innerText = "You enter the store.";
+}
+--fcc-editable-region--
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b1762b7775124622e1a3.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b1762b7775124622e1a3.md
new file mode 100644
index 00000000000..450bc66c133
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b1762b7775124622e1a3.md
@@ -0,0 +1,176 @@
+---
+id: 62a8b1762b7775124622e1a3
+title: Step 60
+challengeType: 0
+dashedName: step-60
+---
+
+# --description--
+
+Instead of assigning the `innerText` and `onclick` properties to specific strings and functions, the `update` function will use data from the `location` that is passed into it. First, that data needs to be passed. Inside the `goTown` function, call the `update` function. Here is an example of calling a function named `myFunction`: `myFunction();`.
+
+# --hints--
+
+You should call the `update` function in the `goTown` function.
+
+```js
+assert.match(goTown.toString(), /update\(\)/);
+```
+
+Don't forget your ending semi-colon.
+
+```js
+assert.match(goTown.toString(), /update\(\);/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+--fcc-editable-region--
+function goTown() {
+
+}
+--fcc-editable-region--
+
+function goStore() {
+
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b3cc436db8139cc5fc09.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b3cc436db8139cc5fc09.md
new file mode 100644
index 00000000000..4d5aa1df9b9
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b3cc436db8139cc5fc09.md
@@ -0,0 +1,170 @@
+---
+id: 62a8b3cc436db8139cc5fc09
+title: Step 61
+challengeType: 0
+dashedName: step-61
+---
+
+# --description--
+
+You now need to pass the `location` argument into the `update` call. You pass arguments by including them within the parentheses of the function call. For example, calling `myFunction` with an `arg` argument would look like: `myFunction(arg)`. Pass your `locations` array into the `update` call.
+
+# --hints--
+
+You should pass the `locations` array into the `update` call.
+
+```js
+assert.match(goTown.toString(), /update\(locations\);/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+--fcc-editable-region--
+function goTown() {
+ update();
+}
+--fcc-editable-region--
+
+function goStore() {
+
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b6536156c51500739b41.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b6536156c51500739b41.md
new file mode 100644
index 00000000000..a8bef26a706
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b6536156c51500739b41.md
@@ -0,0 +1,190 @@
+---
+id: 62a8b6536156c51500739b41
+title: Step 62
+challengeType: 0
+dashedName: step-62
+---
+
+# --description--
+
+The `locations` array contains two locations: the town square and the store. Currently you are passing that entire array into the update functions. Pass in only the first element of the `locations` array by adding `[0]` at the end of the variable. For example: `myFunction(arg[0]);`.
+
+This is called bracket notation. Values in an array are accessed by index. Indices are numerical values and start at 0 - this is called zero-based indexing. `arg[0]` would be the first element in the `arg` array.
+
+# --hints--
+
+You should use bracket notation with `locations`.
+
+```js
+assert.match(code, /locations\[/);
+```
+
+You should access the first object in the `locations` array. Remember that arrays are zero-based.
+
+```js
+assert.match(code, /locations\[0\]/);
+```
+
+You should pass the first object in the `locations` array into the `update` function.
+
+```js
+assert.match(code, /update\(locations\[0\]\);/);
+```
+
+This call should still be in your `goTown()` function.
+
+```js
+assert.match(goTown.toString(), /update\(locations\[0\]\);/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+
+--fcc-editable-region--
+function goTown() {
+ update(locations);
+}
+--fcc-editable-region--
+
+function goStore() {
+
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b711ab7a12161c7d9b67.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b711ab7a12161c7d9b67.md
new file mode 100644
index 00000000000..8a6a5c5c67a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b711ab7a12161c7d9b67.md
@@ -0,0 +1,176 @@
+---
+id: 62a8b711ab7a12161c7d9b67
+title: Step 63
+challengeType: 0
+dashedName: step-63
+---
+
+# --description--
+
+Now your `update` function needs to use the argument you pass into it. Inside the `update` function, change the `button1.innerText` assignment to be `location["button text"]`. That uses bracket notation to get the `button text` property of the `location` object passed into the function.
+
+# --hints--
+
+Your `update` function should use bracket notation to get the `button text` property of the `location` object passed into the function.
+
+```js
+assert.match(update.toString(), /location[('|")button text\1]/);
+```
+
+You should assign the value of the `button text` property of the `location` object to the `innerText` property of `button1`.
+
+```js
+assert.match(update.toString(), /button1\.innerText\s*=\s*location\[('|")button text\1\]/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function update(location) {
+ button1.innerText = "Go to store";
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+--fcc-editable-region--
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b9770050d217d2247801.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b9770050d217d2247801.md
new file mode 100644
index 00000000000..ab4856b1c26
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8b9770050d217d2247801.md
@@ -0,0 +1,176 @@
+---
+id: 62a8b9770050d217d2247801
+title: Step 64
+challengeType: 0
+dashedName: step-64
+---
+
+# --description--
+
+`location["button text"]` is an array with three elements. Change the `button1.innerText` assignment to be the first element of that array instead.
+
+# --hints--
+
+You should access the first element of the `button text` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /location\[('|")button text\1\]\[0\]/);
+```
+
+You should set the `button1.innerText` property to be the first element of the `button text` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /button1\.innerText\s*=\s*location\[('|")button text\1\]\[0\]/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function update(location) {
+ button1.innerText = location["button text"];
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+--fcc-editable-region--
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c0c8313e891a15ec23e7.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c0c8313e891a15ec23e7.md
new file mode 100644
index 00000000000..458368c6e11
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c0c8313e891a15ec23e7.md
@@ -0,0 +1,188 @@
+---
+id: 62a8c0c8313e891a15ec23e7
+title: Step 65
+challengeType: 0
+dashedName: step-65
+---
+
+# --description--
+
+Now update `button2.innerText` and `button3.innerText` to be assigned the second and third values of the `button text` array, respectively.
+
+# --hints--
+
+You should access the second element of the `button text` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /location\[('|")button text\1\]\[1\]/);
+```
+
+You should set the `button2.innerText` property to be the second element of the `button text` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /button2\.innerText\s*=\s*location\[('|")button text\1\]\[1\]/);
+```
+
+You should access the third element of the `button text` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /location\[('|")button text\1\]\[2\]/);
+```
+
+You should set the `button3.innerText` property to be the third element of the `button text` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /button3\.innerText\s*=\s*location\[('|")button text\1\]\[2\]/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = "Go to cave";
+ button3.innerText = "Fight dragon";
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+--fcc-editable-region--
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c1154d3ae11aee80353f.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c1154d3ae11aee80353f.md
new file mode 100644
index 00000000000..4731c369e1e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c1154d3ae11aee80353f.md
@@ -0,0 +1,200 @@
+---
+id: 62a8c1154d3ae11aee80353f
+title: Step 66
+challengeType: 0
+dashedName: step-66
+---
+
+# --description--
+
+Following the same pattern as you did for the button text, update the three buttons' `onclick` assignments to be the first, second, and third values of the `button functions` array.
+
+# --hints--
+
+You should access the first element of the `button functions` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /location\[('|")button functions\1\]\[0\]/);
+```
+
+You should set the `button1.onclick` property to be the second element of the `button functions` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /button1\.onclick\s*=\s*location\[('|")button functions\1\]\[0\]/);
+```
+
+You should access the second element of the `button functions` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /location\[('|")button functions\1\]\[1\]/);
+```
+
+You should set the `button2.onclick` property to be the third element of the `button functions` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /button2\.onclick\s*=\s*location\[('|")button functions\1\]\[1\]/);
+```
+
+You should access the third element of the `button functions` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /location\[('|")button functions\1\]\[2\]/);
+```
+
+You should set the `button3.onclick` property to be the third element of the `button functions` property of the `location` argument.
+
+```js
+assert.match(update.toString(), /button3\.onclick\s*=\s*location\[('|")button functions\1\]\[2\]/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = goStore;
+ button2.onclick = goCave;
+ button3.onclick = fightDragon;
+ text.innerText = "You are in the town square. You see a sign that says \"Store.\"";
+}
+--fcc-editable-region--
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c151b23bf21bc7c4fcba.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c151b23bf21bc7c4fcba.md
new file mode 100644
index 00000000000..ca8a532ec15
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c151b23bf21bc7c4fcba.md
@@ -0,0 +1,176 @@
+---
+id: 62a8c151b23bf21bc7c4fcba
+title: Step 67
+challengeType: 0
+dashedName: step-67
+---
+
+# --description--
+
+Finally, update the `text.innerText` assignment to equal the `text` from the location object. However, instead of using bracket notation, use dot notation. Here is an example of accessing the `name` property of an object called `obj`: `obj.name`.
+
+# --hints--
+
+You should use dot notation to access the `text` property of the `location` object.
+
+```js
+assert.match(update.toString(), /location\.text/);
+```
+
+You should set the `text.innerText` property to be the `text` property of the `location` object.
+
+```js
+assert.match(update.toString(), /text\.innerText\s*=\s*location\.text/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = "You are in the town square. You see a sign that says \"Store\".";
+}
+--fcc-editable-region--
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c173949f851c83c64756.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c173949f851c83c64756.md
new file mode 100644
index 00000000000..422ff092c3e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c173949f851c83c64756.md
@@ -0,0 +1,178 @@
+---
+id: 62a8c173949f851c83c64756
+title: Step 68
+challengeType: 0
+dashedName: step-68
+---
+
+# --description--
+
+Now update your `goStore` function to call the `update` function. Pass the second element of the `locations` array as your argument.
+
+To make sure your refactoring is correct, try clicking your first button again. You should see the same changes to your webpage that you saw earlier.
+
+# --hints--
+
+Your `goStore` function should call the `update` function.
+
+```js
+assert.match(goStore.toString(), /update\(/);
+```
+
+Your `goStore` function should pass the second element of the `locations` array as your argument to `update()`.
+
+```js
+assert.match(goStore.toString(), /update\(locations\[1\]\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c2bbbd8aa82052f47c53.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c2bbbd8aa82052f47c53.md
new file mode 100644
index 00000000000..d96b10aaff6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c2bbbd8aa82052f47c53.md
@@ -0,0 +1,234 @@
+---
+id: 62a8c2bbbd8aa82052f47c53
+title: Step 70
+challengeType: 0
+dashedName: step-70
+---
+
+# --description--
+
+Add a third object to the `locations` array. Give it the same properties as the other two objects.
+
+Set `name` to `cave`. Set `button text` to an array with the strings `Fight slime`, `Fight fanged beast`, and `Go to town square`. Set the `button functions` to an array with the variables `fightSlime`, `fightBeast`, and `goTown`. Set the `text` property to `You enter the cave. You see some monsters.`.
+
+# --hints--
+
+You should have three values in your `locations` array.
+
+```js
+console.log(locations);
+assert.lengthOf(locations, 3);
+```
+
+Your third `locations` value should be an object.
+
+```js
+assert.isObject(locations[2]);
+```
+
+Your third `locations` object should have a `name` property with the value of `cave`.
+
+```js
+assert.equal(locations[2].name, "cave");
+```
+
+Your third `locations` object should have a `button text` property which is an array.
+
+```js
+assert.isArray(locations[2]["button text"]);
+```
+
+Your `button text` property should have the string values `Fight slime`, `Fight fanged beast`, and `Go to town square`.
+
+```js
+assert.equal(locations[2]["button text"][0], "Fight slime");
+assert.equal(locations[2]["button text"][1], "Fight fanged beast");
+assert.equal(locations[2]["button text"][2], "Go to town square");
+```
+
+Your third `locations` object should have a `button functions` property which is an array.
+
+```js
+assert.isArray(locations[2]["button functions"]);
+```
+
+Your `button functions` property should have the function values `fightSlime`, `fightBeast`, and `goTown`.
+
+```js
+assert.equal(locations[2]["button functions"][0], fightSlime);
+assert.equal(locations[2]["button functions"][1], fightBeast);
+assert.equal(locations[2]["button functions"][2], goTown);
+```
+
+Your third `locations` object should have a `text` property which is a string.
+
+```js
+assert.isString(locations[2].text);
+```
+
+Your third `locations` object should have a `text` property with the value of `You enter the cave. You see some monsters.`.
+
+```js
+assert.equal(locations[2].text, "You enter the cave. You see some monsters.");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+--fcc-editable-region--
+
+--fcc-editable-region--
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ console.log("Going to cave.");
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c31ec0ec78216a1c36a0.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c31ec0ec78216a1c36a0.md
new file mode 100644
index 00000000000..1d663fa1670
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c31ec0ec78216a1c36a0.md
@@ -0,0 +1,204 @@
+---
+id: 62a8c31ec0ec78216a1c36a0
+title: Step 71
+challengeType: 0
+dashedName: step-71
+---
+
+# --description--
+
+Now that you have a `cave` location object, update your `goCave` function to call `update` and pass that new `cave` location. Remember that this is the third element in your `locations` array.
+
+Don't forget to remove your `console.log` call!
+
+# --hints--
+
+You should use bracket notation to access the third element in your `locations` array.
+
+```js
+assert.match(code, /locations\[2\]/);
+```
+
+You should pass the third element in your `locations` array to `update`.
+
+```js
+assert.match(code, /update\(locations\[2\]\)/);
+```
+
+You should call `update` with the third element in your `locations` array in your `goCave` function.
+
+```js
+assert.match(goCave.toString(), /update\(locations\[2\]\)/);
+```
+
+You should not have the `console.log` statement in your `goCave` function.
+
+```js
+assert.notMatch(goCave.toString(), /console\.log/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+--fcc-editable-region--
+function goCave() {
+ console.log("Going to cave.");
+}
+--fcc-editable-region--
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+
+}
+
+function buyWeapon() {
+
+}
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c370ad8c68227137e0bc.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c370ad8c68227137e0bc.md
new file mode 100644
index 00000000000..4d33b655a6b
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c370ad8c68227137e0bc.md
@@ -0,0 +1,194 @@
+---
+id: 62a8c370ad8c68227137e0bc
+title: Step 72
+challengeType: 0
+dashedName: step-72
+---
+
+# --description--
+
+Now that your `store` and `cave` locations are complete, you can code the actions the player takes at those locations. Inside the `buyHealth` function, set `gold` equal to `gold` minus `10`.
+
+For example, here is how you would set `num` equal to `5` less than `num`: `num = num - 5;`.
+
+# --hints--
+
+You should subtract `10` from `gold`.
+
+```js
+assert.match(code, /gold\s*=\s*gold\s*-\s*10/);
+```
+
+Your `buyHealth` function should reduce `gold` by `10`.
+
+```js
+gold = 10;
+buyHealth();
+assert.equal(gold, 0);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+--fcc-editable-region--
+function buyHealth() {
+ gold = gold - 10;
+}
+--fcc-editable-region--
+
+function buyWeapon() {
+
+}
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c41ecaf1bd24536129b8.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c41ecaf1bd24536129b8.md
new file mode 100644
index 00000000000..a5bb57d211c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c41ecaf1bd24536129b8.md
@@ -0,0 +1,203 @@
+---
+id: 62a8c41ecaf1bd24536129b8
+title: Step 74
+challengeType: 0
+dashedName: step-74
+---
+
+# --description--
+
+There is a shorthand way to add or subtract from a variable called compound assignment. For example, changing `num = num + 5` to compound assignment would look like `num += 5`.
+
+Update both lines inside your `buyHealth` function to use compound assignment.
+
+# --hints--
+
+You should change `gold` to use compound assignment.
+
+```js
+assert.notMatch(code, /gold\s*=\s*gold\s*-\s*10/);
+```
+
+You should change `health` to use compound assignment.
+
+```js
+assert.notMatch(code, /health\s*=\s*health\s*\+\s*10/);
+```
+
+Your `buyHealth` function should still update the values.
+
+```js
+gold = 10;
+health = 10;
+buyHealth();
+assert.equal(gold, 0);
+assert.equal(health, 20);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+--fcc-editable-region--
+function buyHealth() {
+ gold = gold - 10;
+ health = health + 10;
+}
+--fcc-editable-region--
+
+function buyWeapon() {
+
+}
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c465fa7b0c252f4a8f0c.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c465fa7b0c252f4a8f0c.md
new file mode 100644
index 00000000000..70e928a9bd6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c465fa7b0c252f4a8f0c.md
@@ -0,0 +1,207 @@
+---
+id: 62a8c465fa7b0c252f4a8f0c
+title: Step 75
+challengeType: 0
+dashedName: step-75
+---
+
+# --description--
+
+Now that you are updating the `gold` and `health` variables, you need to display those new values on the game screen. After your assignment lines, assign the `innerText` property of `goldText` to be the variable `gold`. Use the same pattern to update `healthText` with the `health` variable.
+
+Here is an example:
+
+```js
+let value = 100;
+const total = document.querySelector('#total');
+total.innerText = value;
+```
+
+You can test this by clicking your "Go to store" button, followed by your "Buy Health" button.
+
+# --hints--
+
+Your `buyHealth` function should update the text of `healthText` to be the value of `health`.
+
+```js
+health = 10;
+buyHealth();
+const target = document.querySelector('#healthText');
+assert.equal(target.innerText, '20');
+```
+
+Your `buyHealth` function should update the text of `goldText` to be the value of `gold`.
+
+```js
+gold = 10;
+buyHealth();
+const target = document.querySelector('#goldText');
+assert.equal(target.innerText, '0');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+--fcc-editable-region--
+function buyHealth() {
+ gold -= 10;
+ health += 10;
+}
+--fcc-editable-region--
+
+function buyWeapon() {
+
+}
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c4db0710f3260f867a92.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c4db0710f3260f867a92.md
new file mode 100644
index 00000000000..89161b6c20f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c4db0710f3260f867a92.md
@@ -0,0 +1,209 @@
+---
+id: 62a8c4db0710f3260f867a92
+title: Step 76
+challengeType: 0
+dashedName: step-76
+---
+
+# --description--
+
+What if the player doesn't have enough gold to buy health? When you want to run code conditionally, you can use the `if` statement. Put all of the code in your `buyHealth` function inside an `if` statement. For example:
+
+```js
+function myFunction() {
+ if ("condition") {
+ console.log("Hello World!");
+ }
+}
+```
+
+For now, follow that pattern to use a string `condition` inside your `if` statement.
+
+# --hints--
+
+Your `buyHealth` function should have an `if` statement.
+
+```js
+assert.match(buyHealth.toString(), /if/);
+```
+
+Your `if` statement should have the string `condition` for the condition.
+
+```js
+assert.match(buyHealth.toString(), /if\s*\(('|")condition\1\)/);
+```
+
+All of your `buyHealth` code should be inside the `if` statement.
+
+```js
+assert.match(buyHealth.toString(), /if\s*\(('|")condition\1\)\s*\{[\s\S]*\}/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+--fcc-editable-region--
+function buyHealth() {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+}
+--fcc-editable-region--
+
+function buyWeapon() {
+
+}
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c56247609626fa4a8d6e.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c56247609626fa4a8d6e.md
new file mode 100644
index 00000000000..e68eacaf744
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c56247609626fa4a8d6e.md
@@ -0,0 +1,221 @@
+---
+id: 62a8c56247609626fa4a8d6e
+title: Step 77
+challengeType: 0
+dashedName: step-77
+---
+
+# --description--
+
+The `condition` string is just a placeholder. Change the `if` statement condition to check if `gold` is greater than or equal to `10`.
+
+Here is an `if` statement that checks if `num` is greater than or equal to `5`:
+
+```js
+if (num >= 5) {
+
+}
+```
+
+# --hints--
+
+Your `if` statement should check if `gold` is greater than or equal to `10`.
+
+```js
+assert.match(buyHealth.toString(), /if\s*\(gold\s*>=\s*10\)/);
+```
+
+Your `buyHealth` function should update `health` and `gold` if `gold` is greater than or equal to `10`.
+
+```js
+gold = 10;
+health = 10;
+buyHealth();
+assert.equal(health, 20);
+assert.equal(gold, 0);
+const healthElement = document.getElementById('healthText');
+assert.equal(healthElement.innerText, '20');
+const goldElement = document.getElementById('goldText');
+assert.equal(goldElement.innerText, '0');
+```
+
+Your `buyHealth` function should not update `health` and `gold` if `gold` is less than `10`.
+
+```js
+gold = 5;
+health = 10;
+buyHealth();
+assert.equal(health, 10);
+assert.equal(gold, 5);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+--fcc-editable-region--
+function buyHealth() {
+ if ("condition") {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ }
+}
+--fcc-editable-region--
+
+function buyWeapon() {
+
+}
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c5db7888af27af23f0dd.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c5db7888af27af23f0dd.md
new file mode 100644
index 00000000000..d29d4fa92c7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c5db7888af27af23f0dd.md
@@ -0,0 +1,206 @@
+---
+id: 62a8c5db7888af27af23f0dd
+title: Step 78
+challengeType: 0
+dashedName: step-78
+---
+
+# --description--
+
+Now when a player tries to buy health it will only work if they have enough money. If they do not, nothing will happen. Add an `else` statement where you can put code to run if a player does not have enough money.
+
+Here is an example of an empty `else` statement:
+
+```js
+if (num >= 5) {
+
+} else {
+
+}
+```
+
+# --hints--
+
+Your `buyHealth` function should have an `else` statement.
+
+```js
+assert.match(buyHealth.toString(), /else/);
+```
+
+Your `else` statement should come after your `if` statement.
+
+```js
+const split = buyHealth.toString().split(/\s/);
+assert.isAbove(split.indexOf('else'), split.indexOf('if'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+--fcc-editable-region--
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ }
+}
+--fcc-editable-region--
+
+function buyWeapon() {
+
+}
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c65b75664c28a8e59c16.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c65b75664c28a8e59c16.md
new file mode 100644
index 00000000000..3ef17db2434
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c65b75664c28a8e59c16.md
@@ -0,0 +1,200 @@
+---
+id: 62a8c65b75664c28a8e59c16
+title: Step 79
+challengeType: 0
+dashedName: step-79
+---
+
+# --description--
+
+Inside the `else` statement, set `text.innerText` to equal `You do not have enough gold to buy health.`.
+
+# --hints--
+
+Your `buyHealth` function should set `text.innerText` to equal `You do not have enough gold to buy health.`.
+
+```js
+assert.match(buyHealth.toString(), /text\.innerText\s*=\s*('|")You do not have enough gold to buy health\.\1/);
+```
+
+Your `buyHealth` function should update `text.innerText` when `gold` is less than `10`.
+
+```js
+gold = 5;
+health = 10;
+buyHealth();
+assert.equal(text.innerText, 'You do not have enough gold to buy health.');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+--fcc-editable-region--
+
+--fcc-editable-region--
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+
+}
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c7322e42962ad53ad204.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c7322e42962ad53ad204.md
new file mode 100644
index 00000000000..bed05c8d88b
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c7322e42962ad53ad204.md
@@ -0,0 +1,229 @@
+---
+id: 62a8c7322e42962ad53ad204
+title: Step 81
+challengeType: 0
+dashedName: step-81
+---
+
+# --description--
+
+Just like your `locations` array, your `weapons` array will hold objects. Add four objects to the `weapons` array, each with two properties: `name` and `power`. The first should have the `name` set to `stick` and the `power` set to `5`. The second should be `dagger` and `30`. The third, `claw hammer` and `50`. The fourth, `sword` and `100`.
+
+# --hints--
+
+Your `weapons` array should have four values.
+
+```js
+assert.lengthOf(weapons, 4);
+```
+
+Your `weapons` array should have four objects.
+
+```js
+assert.isObject(weapons[0]);
+assert.isObject(weapons[1]);
+assert.isObject(weapons[2]);
+assert.isObject(weapons[3]);
+```
+
+Your first `weapons` object should have the `name` set to `stick` and the `power` set to `5`.
+
+```js
+assert.equal(weapons[0].name, 'stick');
+assert.equal(weapons[0].power, 5);
+```
+
+Your second `weapons` object should have the `name` set to `dagger` and the `power` set to `30`.
+
+```js
+assert.equal(weapons[1].name, 'dagger');
+assert.equal(weapons[1].power, 30);
+```
+
+Your third `weapons` object should have the `name` set to `claw hammer` and the `power` set to `50`.
+
+```js
+assert.equal(weapons[2].name, 'claw hammer');
+assert.equal(weapons[2].power, 50);
+```
+
+Your fourth `weapons` object should have the `name` set to `sword` and the `power` set to `100`.
+
+```js
+assert.equal(weapons[3].name, 'sword');
+assert.equal(weapons[3].power, 100);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c8cee8e5cf2e001789b4.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c8cee8e5cf2e001789b4.md
new file mode 100644
index 00000000000..7f2575cbb11
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8c8cee8e5cf2e001789b4.md
@@ -0,0 +1,219 @@
+---
+id: 62a8c8cee8e5cf2e001789b4
+title: Step 84
+challengeType: 0
+dashedName: step-84
+---
+
+# --description--
+
+The value of the `currentWeapon` variable corresponds to an index in the `weapons` array. The player starts with a `stick`, since `currentWeapon` starts at `0` and `weapons[0]` is the `stick` weapon.
+
+In the `buyWeapon` function, add one to `currentWeapon` - the user is buying the next weapon in the `weapons` array.
+
+# --hints--
+
+You should use compound assignment to add one to `currentWeapon`.
+
+```js
+assert.match(buyWeapon.toString(), /currentWeapon\s*\+=\s*1/);
+```
+
+Your `buyWeapon` function should increase `currentWeapon` by `1`.
+
+```js
+gold = 30;
+currentWeapon = 0;
+buyWeapon();
+assert.equal(currentWeapon, 1);
+```
+
+Your code should be in your `if` statement.
+
+```js
+gold = 20;
+currentWeapon = 0;
+buyWeapon();
+assert.equal(currentWeapon, 0);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+ gold -= 30;
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ca22d29fe62f3952bdf5.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ca22d29fe62f3952bdf5.md
new file mode 100644
index 00000000000..dbd8006158d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ca22d29fe62f3952bdf5.md
@@ -0,0 +1,208 @@
+---
+id: 62a8ca22d29fe62f3952bdf5
+title: Step 85
+challengeType: 0
+dashedName: step-85
+---
+
+# --description--
+
+Increasing a value by 1, or incrementing, has a special operator in JavaScript: `++`. If you wanted to increase `num` by 1, you could write `num++`.
+
+Change your `currentWeapon` assignment to use the increment operator.
+
+# --hints--
+
+You should use the increment operator to increase `currentWeapon` by `1`.
+
+```js
+assert.match(buyWeapon.toString(), /currentWeapon\s*\+\s*\+/);
+```
+
+You should not use compound assignment to increase `currentWeapon` by `1`.
+
+```js
+assert.notMatch(buyWeapon.toString(), /currentWeapon\s*\+=\s*1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon += 1;
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cb19bd7f8a304e5427a1.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cb19bd7f8a304e5427a1.md
new file mode 100644
index 00000000000..29c3d761fb0
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cb19bd7f8a304e5427a1.md
@@ -0,0 +1,206 @@
+---
+id: 62a8cb19bd7f8a304e5427a1
+title: Step 86
+challengeType: 0
+dashedName: step-86
+---
+
+# --description--
+
+Now update the `goldText` element to display the new value of `gold`, and update the `text` element to display `You now have a new weapon.`.
+
+# --hints--
+
+You should update the `innerText` property of the `goldText` element to be `gold`.
+
+```js
+assert.match(buyWeapon.toString(), /goldText\.innerText\s*=\s*gold/);
+```
+
+You should update the `innerText` property of the `text` element to be `You now have a new weapon.`.
+
+```js
+assert.match(buyWeapon.toString(), /text\.innerText\s*=\s*('|")You now have a new weapon\.\1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cbd1e3595431d5a2b3f1.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cbd1e3595431d5a2b3f1.md
new file mode 100644
index 00000000000..d91e6245ebe
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cbd1e3595431d5a2b3f1.md
@@ -0,0 +1,222 @@
+---
+id: 62a8cbd1e3595431d5a2b3f1
+title: Step 87
+challengeType: 0
+dashedName: step-87
+---
+
+# --description--
+
+You should tell the player what weapon they bought. In between the two lines you just wrote, use `let` to initialize a new variable called `newWeapon`. Set this to equal `weapons`.
+
+# --hints--
+
+Your `buyWeapon` function should have a variable named `newWeapon`.
+
+```js
+assert.match(buyWeapon.toString(), /newWeapon/);
+```
+
+You should use `let` to declare `newWeapon`.
+
+```js
+assert.match(code, /let\s+newWeapon/);
+```
+
+`newWeapon` should be initialised to have the value of `weapons`. Don't forget your semi-colon.
+
+```js
+assert.match(buyWeapon.toString(), /newWeapon\s*=\s*weapons;/);
+```
+
+`newWeapon` should be declared before you modify `text`.
+
+```js
+const contents = buyWeapon.toString().split(/\s+/);
+assert.isBelow(contents.indexOf('newWeapon'), contents.indexOf('text.innerText'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyWeapon, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+
+ text.innerText = "You now have a new weapon.";
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cce1b0c32c33017cf2e9.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cce1b0c32c33017cf2e9.md
new file mode 100644
index 00000000000..165962a1920
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cce1b0c32c33017cf2e9.md
@@ -0,0 +1,211 @@
+---
+id: 62a8cce1b0c32c33017cf2e9
+title: Step 88
+challengeType: 0
+dashedName: step-88
+---
+
+# --description--
+
+For your `newWeapon` variable, use bracket notation to use the `currentWeapon` variable to access an object within the `weapons` array.
+
+When you use a variable in bracket notation, you are accessing the property or index by the *value* of that variable.
+
+For example, this code uses the `index` variable to access a value of `array`.
+
+```js
+let value = array[index];
+```
+
+# --hints--
+
+You should update `newWeapon` to have the value of `weapons[currentWeapon]`.
+
+```js
+assert.match(buyWeapon.toString(), /newWeapon\s*=\s*weapons\[currentWeapon\]/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon];
+ text.innerText = "You now have a new weapon.";
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ce73d0dce43468f6689c.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ce73d0dce43468f6689c.md
new file mode 100644
index 00000000000..4b1f8fb6cb6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ce73d0dce43468f6689c.md
@@ -0,0 +1,222 @@
+---
+id: 62a8ce73d0dce43468f6689c
+title: Step 90
+challengeType: 0
+dashedName: step-90
+---
+
+# --description--
+
+You can insert variables into a string with the concatenation operator `+`. Update the `You now have a new weapon.` string to say `You now have a ` and the name of the new weapon. Remember to end the sentence with a period.
+
+Here is an example that creates the string `Hello, our name is freeCodeCamp.`:
+
+```js
+const ourName = "freeCodeCamp";
+const ourStr = "Hello, our name is " + ourName + ".";
+```
+
+# --hints--
+
+You should update the `text.innerText` assignment to start with the string `You now have a `.
+
+```js
+assert.match(buyWeapon.toString(), /text\.innerText\s*=\s*('|")You now have a \1/);
+```
+
+You should use the concatenation operator to add `newWeapon` to the end of the `text.innerText` string.
+
+```js
+assert.match(buyWeapon.toString(), /text\.innerText\s*=\s*('|")You now have a \1\s*\+\s*newWeapon/);
+```
+
+You should use the concatenation operator to end your `text.innerText` string with a `.`.
+
+```js
+assert.match(buyWeapon.toString(), /text\.innerText\s*=\s*('|")You now have a \1\s*\+\s*newWeapon\s*\+\s*('|")\.\2/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a new weapon.";
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cf22272d6d35af80d4ac.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cf22272d6d35af80d4ac.md
new file mode 100644
index 00000000000..748ab4d2f08
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8cf22272d6d35af80d4ac.md
@@ -0,0 +1,229 @@
+---
+id: 62a8cf22272d6d35af80d4ac
+title: Step 91
+challengeType: 0
+dashedName: step-91
+---
+
+# --description--
+
+Back at the beginning of this project, you created the `inventory` array. Add the `newWeapon` to the end of the `inventory` array using the `push()` method.
+
+Here is an example:
+
+```js
+const arr = ["first"];
+const next = "second";
+arr.push(next);
+```
+
+`arr` would now have the value `["first", "second"]`.
+
+# --hints--
+
+You should use the `push` method on `inventory`.
+
+```js
+assert.match(buyWeapon.toString(), /inventory\.push/)
+```
+
+You should `push` the value of `newWeapon` to the `inventory` array.
+
+```js
+assert.match(buyWeapon.toString(), /inventory\.push\s*\(\s*newWeapon\s*\)/)
+```
+
+Your `buyWeapon` function should add the value of `newWeapon` to the `inventory` array.
+
+```js
+inventory = [];
+currentWeapon = 0;
+buyWeapon();
+assert.deepEqual(inventory, ["dagger"]);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d0337d7c67377a4a76c6.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d0337d7c67377a4a76c6.md
new file mode 100644
index 00000000000..b7219fb9be1
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d0337d7c67377a4a76c6.md
@@ -0,0 +1,218 @@
+---
+id: 62a8d0337d7c67377a4a76c6
+title: Step 92
+challengeType: 0
+dashedName: step-92
+---
+
+# --description--
+
+Up until now, any time `text.innerText` was updated the old text was erased. This time, use the `+=` operator to add text to the end of `text.innerText`. Add the string ` In your inventory you have: ` - include the spaces at the beginning and the end.
+
+# --hints--
+
+You should add a new line with `text.innerText`.
+
+```js
+const matches = buyWeapon.toString().match(/text\.innerText/g);
+assert.lengthOf(matches, 2);
+```
+
+You should use the `+=` operator to add to `text.innerText`.
+
+```js
+assert.match(buyWeapon.toString(), /text\.innerText\s*\+=\s*/)
+```
+
+You should add the string ` In your inventory you have: ` to the end of `text.innerText`. Mind the spaces!
+
+```js
+assert.match(buyWeapon.toString(), /text\.innerText\s*\+=\s*('|")\sIn your inventory you have:\s\1/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d08668fa8b38732486e9.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d08668fa8b38732486e9.md
new file mode 100644
index 00000000000..098be4a56e6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d08668fa8b38732486e9.md
@@ -0,0 +1,211 @@
+---
+id: 62a8d08668fa8b38732486e9
+title: Step 93
+challengeType: 0
+dashedName: step-93
+---
+
+# --description--
+
+At the end of the second `text.innerText` string you just added, use the concatenation operator to add the contents of `inventory` to the string.
+
+# --hints--
+
+You should not change the ` In your inventory you have: ` string.
+
+```js
+assert.match(buyWeapon.toString(), /text\.innerText\s*\+=\s*('|")\sIn your inventory you have:\s\1/)
+```
+
+You should use the concatenation operator `+` to add the contents of `inventory` to the string.
+
+```js
+assert.match(buyWeapon.toString(), /text\.innerText\s*\+=\s*('|")\sIn your inventory you have:\s\1\s*\+\s*inventory/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: ";
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d0c4f12c2239b6618582.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d0c4f12c2239b6618582.md
new file mode 100644
index 00000000000..3ebebb1edd6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d0c4f12c2239b6618582.md
@@ -0,0 +1,226 @@
+---
+id: 62a8d0c4f12c2239b6618582
+title: Step 94
+challengeType: 0
+dashedName: step-94
+---
+
+# --description--
+
+Add an `else` statement to your `buyWeapon` function. In that statement, set `text.innerText` to equal `You do not have enough gold to buy a weapon.`.
+
+# --hints--
+
+You should add an `else` statement to your `buyWeapon` function.
+
+```js
+assert.match(buyWeapon.toString(), /else/);
+```
+
+Your `else` statement should come after your `if` statement.
+
+```js
+const split = buyWeapon.toString().split(/\s|\n/);
+assert.isAbove(split.indexOf('else'), split.indexOf('if'));
+```
+
+You should set `text.innerText` to `You do not have enough gold to buy a weapon.`.
+
+```js
+assert.match(buyWeapon.toString(), /text.innerText\s*=\s*('|")You do not have enough gold to buy a weapon.\1/);
+```
+
+Your `else` statement should set `text.innerText` to `You do not have enough gold to buy a weapon.`.
+
+```js
+gold = 20;
+buyWeapon();
+assert.equal(text.innerText, 'You do not have enough gold to buy a weapon.');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d0fdf2dad83a92883a80.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d0fdf2dad83a92883a80.md
new file mode 100644
index 00000000000..1c2b1476e8f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d0fdf2dad83a92883a80.md
@@ -0,0 +1,225 @@
+---
+id: 62a8d0fdf2dad83a92883a80
+title: Step 95
+challengeType: 0
+dashedName: step-95
+---
+
+# --description--
+
+Once a player has the best weapon, they cannot buy another one. Wrap all of the code in your `buyWeapon` function inside another `if` statement. The condition should check if `currentWeapon` is less than `3` - the index of the last weapon.
+
+# --hints--
+
+You should have a new `if` statement that checks if `currentWeapon` is less than `3`.
+
+```js
+assert.match(buyWeapon.toString(), /currentWeapon\s*\<\s*3/)
+```
+
+Your existing `if` statement should be within your new `if` statement.
+
+```js
+currentWeapon = 5;
+gold = 50;
+buyWeapon();
+assert.equal(gold, 50);
+```
+
+Your existing `else` statement should be within your new `if` statement.
+
+```js
+currentWeapon = 5;
+gold = 10;
+buyWeapon();
+assert.notEqual(text.innerText, "You do not have enough gold to buy a weapon.");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d143f2a58e3b6d6e9c33.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d143f2a58e3b6d6e9c33.md
new file mode 100644
index 00000000000..a705f22a61f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d143f2a58e3b6d6e9c33.md
@@ -0,0 +1,215 @@
+---
+id: 62a8d143f2a58e3b6d6e9c33
+title: Step 96
+challengeType: 0
+dashedName: step-96
+---
+
+# --description--
+
+Arrays have a `length` property that returns the number of items in the array. You may want to add new values to the `weapons` array in the future. Change your `if` condition to check if `currentWeapon` is less than the length of the `weapons` array. An example of checking the length of an array `myArray` would look like `myArray.length`.
+
+# --hints--
+
+You should use the `length` property on the `weapons` array.
+
+```js
+assert.match(buyWeapon.toString(), /weapons\.length/);
+```
+
+Your `if` statement should check if `currentWeapon` is less than `weapons.length`.
+
+```js
+assert.match(buyWeapon.toString(), /currentWeapon\s*<\s*weapons\.length/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (currentWeapon < 3) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d1c72e8bb13c2074d93c.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d1c72e8bb13c2074d93c.md
new file mode 100644
index 00000000000..4db3e483fce
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d1c72e8bb13c2074d93c.md
@@ -0,0 +1,215 @@
+---
+id: 62a8d1c72e8bb13c2074d93c
+title: Step 97
+challengeType: 0
+dashedName: step-97
+---
+
+# --description--
+
+You now have an error to fix. The `currentWeapon` variable is the index of the `weapons` array, but array indexing starts at zero. The index of the last element in an array is one less than the length of the array. Change the `if` condition to check `weapons.length - 1`, instead of `weapons.length`.
+
+# --hints--
+
+You should update the condition to subtract `1` from `weapons.length`.
+
+```js
+assert.match(buyWeapon.toString(), /weapons\.length\s*-\s*1/);
+```
+
+Your condition should check if `currentWeapon` is less than `weapons.length - 1`.
+
+```js
+assert.match(buyWeapon.toString(), /currentWeapon\s*<\s*weapons\.length\s*-\s*1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (currentWeapon < weapons.length) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d2146a3e853d0a6e28ca.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d2146a3e853d0a6e28ca.md
new file mode 100644
index 00000000000..2061307615c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d2146a3e853d0a6e28ca.md
@@ -0,0 +1,224 @@
+---
+id: 62a8d2146a3e853d0a6e28ca
+title: Step 98
+challengeType: 0
+dashedName: step-98
+---
+
+# --description--
+
+Add an `else` statement for your outer `if` statement. Inside this new `else` statement, set `text.innerText` to `You already have the most powerful weapon!`.
+
+# --hints--
+
+You should have another `else` statement in your `buyWeapon` function.
+
+```js
+const matches = buyWeapon.toString().match(/else/g);
+assert.equal(matches.length, 2);
+```
+
+You should set `text.innerText` to `You already have the most powerful weapon!`.
+
+```js
+assert.match(buyWeapon.toString(), /('|")You already have the most powerful weapon!\1/);
+```
+
+You should modify your `text.innerText` to `You already have the most powerful weapon!` within your outer `else` statement.
+
+```js
+currentWeapon = 5;
+buyWeapon();
+assert.equal(text.innerText, "You already have the most powerful weapon!");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+--fcc-editable-region--
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d24c97461b3ddb9397c8.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d24c97461b3ddb9397c8.md
new file mode 100644
index 00000000000..cd0c1476164
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d24c97461b3ddb9397c8.md
@@ -0,0 +1,229 @@
+---
+id: 62a8d24c97461b3ddb9397c8
+title: Step 99
+challengeType: 0
+dashedName: step-99
+---
+
+# --description--
+
+Once a player has the most powerful weapon, you can give them the ability to sell their old weapons. In the outer `else` statement, set `button2.innerText` to `Sell weapon for 15 gold`. Also set `button2.onclick` to the function name `sellWeapon`.
+
+# --hints--
+
+You should set the value of `button2.innerText`.
+
+```js
+assert.match(buyWeapon.toString(), /button2\.innerText/);
+```
+
+You should set the value of `button2.innerText` to `Sell weapon for 15 gold`.
+
+```js
+assert.match(buyWeapon.toString(), /button2\.innerText\s*=\s*('|")Sell weapon for 15 gold\1;/);
+```
+
+You should set the value of `button2.onclick`.
+
+```js
+assert.match(buyWeapon.toString(), /button2\.onclick/);
+```
+
+You should set the value of `button2.onclick` to `sellWeapon`.
+
+```js
+assert.match(buyWeapon.toString(), /button2\.onclick\s*=\s*sellWeapon;/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d31ebbc10e3fe1b28e03.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d31ebbc10e3fe1b28e03.md
new file mode 100644
index 00000000000..77100cf5462
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d31ebbc10e3fe1b28e03.md
@@ -0,0 +1,223 @@
+---
+id: 62a8d31ebbc10e3fe1b28e03
+title: Step 101
+challengeType: 0
+dashedName: step-101
+---
+
+# --description--
+
+Players should not be able to sell their only weapon. Inside the `sellWeapon` function, add an `if` statement with a condition that checks if the length of the `inventory` array is greater than `1`.
+
+# --hints--
+
+Your `sellWeapon` function should have an `if` statement.
+
+```js
+assert.match(sellWeapon.toString(), /if/);
+```
+
+Your `if` statement should check if `inventory.length` is greater than `1`.
+
+```js
+assert.match(sellWeapon.toString(), /if\s*\(inventory\.length\s*>\s*1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+--fcc-editable-region--
+function sellWeapon() {
+
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d35660db4040ba292193.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d35660db4040ba292193.md
new file mode 100644
index 00000000000..dbbf432519d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d35660db4040ba292193.md
@@ -0,0 +1,234 @@
+---
+id: 62a8d35660db4040ba292193
+title: Step 102
+challengeType: 0
+dashedName: step-102
+---
+
+# --description--
+
+Inside the `if` statement, set `gold` equal to `15` more than its current value. Also update `goldText.innerText` to the new value.
+
+# --hints--
+
+You should use compound assignment to increase `gold` by `15`.
+
+```js
+assert.match(sellWeapon.toString(), /gold\s*\+=\s*15/);
+```
+
+You should set `goldText.innerText` to `gold`.
+
+```js
+assert.match(sellWeapon.toString(), /goldText\.innerText\s*=\s*gold/);
+```
+
+Your code should be in your `if` statement.
+
+```js
+inventory = ["Naomi"];
+gold = 0
+sellWeapon();
+assert.equal(gold, 0);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+--fcc-editable-region--
+function sellWeapon() {
+ if (inventory.length > 1) {
+
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d382cd075f4169223e14.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d382cd075f4169223e14.md
new file mode 100644
index 00000000000..8f3764e0ef9
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d382cd075f4169223e14.md
@@ -0,0 +1,223 @@
+---
+id: 62a8d382cd075f4169223e14
+title: Step 103
+challengeType: 0
+dashedName: step-103
+---
+
+# --description--
+
+Use the `let` keyword to create a variable named `currentWeapon`. Don't assign it a value yet.
+
+Notice that you already have a `currentWeapon` variable elsewhere in your code. Since you are using the `let` keyword instead of `var`, the new `currentWeapon` is scoped only to this `if` statement. At the close of the `if` statement, the old `currentWeapon` will be used again.
+
+# --hints--
+
+You should use `let` to declare a `currentWeapon` variable.
+
+```js
+assert.match(sellWeapon.toString(), /currentWeapon/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+--fcc-editable-region--
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d539dc11cb42b5dd7ec8.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d539dc11cb42b5dd7ec8.md
new file mode 100644
index 00000000000..1fb5303efc5
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d539dc11cb42b5dd7ec8.md
@@ -0,0 +1,233 @@
+---
+id: 62a8d539dc11cb42b5dd7ec8
+title: Step 104
+challengeType: 0
+dashedName: step-104
+---
+
+# --description--
+
+The `shift()` method on an array removes the first element in the array and returns it. Use this method to take the first element from the `inventory` array and assign it to your `currentWeapon` variable.
+
+# --hints--
+
+Your `sellWeapon` function should use the `shift()` method.
+
+```js
+assert.match(sellWeapon.toString(), /shift\(\)/);
+```
+
+You should use the `shift()` method on the `inventory` array.
+
+```js
+assert.match(sellWeapon.toString(), /inventory\.shift\(\)/);
+```
+
+You should assign the value of `inventory.shift()` to your `currentWeapon` variable.
+
+```js
+assert.match(sellWeapon.toString(), /currentWeapon\s*=\s*inventory\.shift\(\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+--fcc-editable-region--
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon;
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d61ddfe35744369365b7.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d61ddfe35744369365b7.md
new file mode 100644
index 00000000000..03e5cceea99
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d61ddfe35744369365b7.md
@@ -0,0 +1,249 @@
+---
+id: 62a8d61ddfe35744369365b7
+title: Step 105
+challengeType: 0
+dashedName: step-105
+---
+
+# --description--
+
+After your `currentWeapon`, use the concatenation operator to set `text.innerText` to the string `You sold a `, then `currentWeapon`, then the string `.`.
+
+# --hints--
+
+You should use the assignment operator with `text.innerText`.
+
+```js
+assert.match(sellWeapon.toString(), /text\.innerText\s*=/);
+```
+
+You should add `You sold a ` to `text.innerText`. Spacing is important.
+
+```js
+assert.match(sellWeapon.toString(), /text\.innerText\s*=\s*('|")You sold a \1/);
+```
+
+You should add the value of `currentWeapon` to the `You sold a ` string. Use the concatenation operator to do this on the same line.
+
+```js
+assert.match(sellWeapon.toString(), /text\.innerText\s*=\s*('|")You sold a\s\1\s*\+\s*\_currentWeapon/);
+```
+
+You should add the string `.` to the value of `currentWeapon`. Use the concatenation operator to do this on the same line.
+
+```js
+assert.match(sellWeapon.toString(), /text\.innerText\s*=\s*('|")You sold a \1\s*\+\s*\_currentWeapon\s+\+\s+('|")\.\2/);
+```
+
+Your `text.innerText` should update to the proper string.
+
+```js
+inventory = ["first", "second"];
+text.innerText = "Hello";
+sellWeapon();
+assert.equal(text.innerText, "You sold a first.");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+--fcc-editable-region--
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d6c7001ebc45350e3d16.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d6c7001ebc45350e3d16.md
new file mode 100644
index 00000000000..bc8435faa22
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d6c7001ebc45350e3d16.md
@@ -0,0 +1,243 @@
+---
+id: 62a8d6c7001ebc45350e3d16
+title: Step 106
+challengeType: 0
+dashedName: step-106
+---
+
+# --description--
+
+Now use the `+=` operator to add the string ` In your inventory you have: ` and the contents of `inventory` to the `text.innerText`. Make sure to include the space at the beginning and end of the ` In your inventory you have: ` string.
+
+# --hints--
+
+You should add another `text.innerText` line.
+
+```js
+const matches = sellWeapon.toString().match(/text\.innerText/g);
+assert.equal(matches.length, 2);
+```
+
+You should use compound assignment on `text.innerText`.
+
+```js
+const matches = sellWeapon.toString().match(/text\.innerText\s*\+=/g);
+assert.equal(matches.length, 1);
+```
+
+You should add the string ` In your inventory you have: ` to the second `text.innerText` line. Spacing matters.
+
+```js
+assert.match(sellWeapon.toString(), /text\.innerText\s*\+=\s*('|") In your inventory you have: \1/);
+```
+
+You should use the concatenation operator to add the value of `inventory` to the end of your second `text.innerText` line.
+
+```js
+assert.match(sellWeapon.toString(), /text\.innerText\s*\+=\s*('|") In your inventory you have: \1\s*\+\s*inventory/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+--fcc-editable-region--
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d7b8ab568b4649998954.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d7b8ab568b4649998954.md
new file mode 100644
index 00000000000..3e59ee00a2d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d7b8ab568b4649998954.md
@@ -0,0 +1,237 @@
+---
+id: 62a8d7b8ab568b4649998954
+title: Step 107
+challengeType: 0
+dashedName: step-107
+---
+
+# --description--
+
+Use an `else` statement to run when the `inventory` length is not more than one. Set the `text.innerText` to say `Don't sell your only weapon!`.
+
+# --hints--
+
+Your `sellWeapon` function should have an `else` statement.
+
+```js
+assert.match(sellWeapon.toString(), /else/);
+```
+
+You should set `text.innerText` to `Don't sell your only weapon!`.
+
+```js
+assert.match(sellWeapon.toString(), /text\.innerText\s*=\s*('|")Don't sell your only weapon!\1/);
+```
+
+Your new `text.innerText` line should be in your `else` statement.
+
+```js
+inventory = ["Naomi"];
+sellWeapon();
+assert.equal(text.innerText, "Don't sell your only weapon!");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+--fcc-editable-region--
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ }
+}
+--fcc-editable-region--
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d81f539f004776dd9b1e.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d81f539f004776dd9b1e.md
new file mode 100644
index 00000000000..f47ecd3e581
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8d81f539f004776dd9b1e.md
@@ -0,0 +1,310 @@
+---
+id: 62a8d81f539f004776dd9b1e
+title: Step 108
+challengeType: 0
+dashedName: step-108
+---
+
+# --description--
+
+Now you can start the code to fight monsters. To keep your code organized, your `fightDragon` function has been moved for you to be near the other `fight` functions.
+
+Below your `weapons` array, define a `monsters` variable and assign it an array. Set that array to have three objects, each with a `name`, `level`, and `health` properties. The first object's values should be `slime`, `2`, and `15`, in order. The second should be `fanged beast`, `8`, and `60`. The third should be `dragon`, `20`, and `300`.
+
+# --hints--
+
+You should use `const` to declare a `monsters` variable.
+
+```js
+assert.match(code, /const\s*monsters/);
+```
+
+Your `monsters` variable should be an array.
+
+```js
+assert.isArray(monsters);
+```
+
+Your `monsters` variable should have 3 values.
+
+```js
+assert.lengthOf(monsters, 3);
+```
+
+Your `monsters` array should have 3 objects.
+
+```js
+assert(monsters.every(val => typeof val === "object"));
+```
+
+The first value in your `monsters` array should have an object with a `name` property set to `slime`.
+
+```js
+assert.equal(monsters[0].name, "slime");
+```
+
+The first value in your `monsters` array should have an object with a `level` property set to `2`.
+
+```js
+assert.equal(monsters[0].level, 2);
+```
+
+The first value in your `monsters` array should have an object with a `health` property set to `15`.
+
+```js
+assert.equal(monsters[0].health, 15);
+```
+
+The second value in your `monsters` array should have an object with a `name` property set to `fanged beast`.
+
+```js
+assert.equal(monsters[1].name, "fanged beast");
+```
+
+The second value in your `monsters` array should have an object with a `level` property set to `8`.
+
+```js
+assert.equal(monsters[1].level, 8);
+```
+
+The second value in your `monsters` array should have an object with a `health` property set to `60`.
+
+```js
+assert.equal(monsters[1].health, 60);
+```
+
+The third value in your `monsters` array should have an object with a `name` property set to `dragon`.
+
+```js
+assert.equal(monsters[2].name, "dragon");
+```
+
+The third value in your `monsters` array should have an object with a `level` property set to `20`.
+
+```js
+assert.equal(monsters[2].level, 20);
+```
+
+The third value in your `monsters` array should have an object with a `health` property set to `300`.
+
+```js
+assert.equal(monsters[2].health, 300);
+```
+
+You should not add any extra properties to your objects.
+
+```js
+assert.deepEqual(monsters, [
+ {name: "slime", level: 2, health: 15},
+ {name: "fanged beast", level: 8, health: 60},
+ {name: "dragon", level: 20, health: 300}
+])
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+--fcc-editable-region--
+
+--fcc-editable-region--
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8dd468debb449b4454086.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8dd468debb449b4454086.md
new file mode 100644
index 00000000000..4167fc0a12b
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8dd468debb449b4454086.md
@@ -0,0 +1,250 @@
+---
+id: 62a8dd468debb449b4454086
+title: Step 109
+challengeType: 0
+dashedName: step-109
+---
+
+# --description--
+
+Fighting each type of monster will use similar logic. Create an empty function called `goFight` to manage this logic.
+
+# --hints--
+
+You should use the `function` keyword to declare `goFight`.
+
+```js
+assert.match(code, /function\s*goFight/);
+```
+
+`goFight` should be an empty function.
+
+```js
+assert.match(goFight.toString(), /goFight\s*\(\s*\)\s*\{\s*\}/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+
+}
+
+function fightBeast() {
+
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8dd9cdb16324b04cfd958.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8dd9cdb16324b04cfd958.md
new file mode 100644
index 00000000000..b960134fac7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8dd9cdb16324b04cfd958.md
@@ -0,0 +1,260 @@
+---
+id: 62a8dd9cdb16324b04cfd958
+title: Step 110
+challengeType: 0
+dashedName: step-110
+---
+
+# --description--
+
+In your `fightSlime` function, set `fighting` equal to `0` - the index of `slime` in the `monsters` array. Remember that you already declared `fighting` earlier in your code, so you do not need `let` or `const` here.
+
+On the next line, call the `goFight` function.
+
+# --hints--
+
+You should set `fighting` equal to `0`.
+
+```js
+assert.match(fightSlime.toString(), /fighting\s*=\s*0;/);
+```
+
+You should not use `let` or `const`.
+
+```js
+assert.notMatch(fightSlime.toString(), /let|const|var/);
+```
+
+You should call the `goFight` function.
+
+```js
+assert.match(fightSlime.toString(), /goFight\(\);/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+--fcc-editable-region--
+function fightSlime() {
+
+}
+--fcc-editable-region--
+
+function fightBeast() {
+
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+
+function goFight() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8dfcf7fb1044d2f478fd1.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8dfcf7fb1044d2f478fd1.md
new file mode 100644
index 00000000000..aa331ca8991
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8dfcf7fb1044d2f478fd1.md
@@ -0,0 +1,259 @@
+---
+id: 62a8dfcf7fb1044d2f478fd1
+title: Step 111
+challengeType: 0
+dashedName: step-111
+---
+
+# --description--
+
+Following the same pattern, use that code in the `fightBeast` and `fightDragon` functions. Remember that `beast` is at index `1` and `dragon` is at index `2`. Also remove the `console.log` call from your `fightDragon` function.
+
+# --hints--
+
+You should set `fighting` to `1` in your `fightBeast` function.
+
+```js
+assert.match(fightBeast.toString(), /fighting\s*=\s*1;/);
+```
+
+You should set `fighting` to `2` in your `fightDragon` function.
+
+```js
+assert.match(fightDragon.toString(), /fighting\s*=\s*2;/);
+```
+
+You should remove the `console.log` from your `fightDragon` function.
+
+```js
+assert.notMatch(fightDragon.toString(), /console\.log/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+--fcc-editable-region--
+function fightBeast() {
+
+}
+
+function fightDragon() {
+ console.log("Fighting dragon.");
+}
+--fcc-editable-region--
+
+function goFight() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e0d1d0110b4ec421489f.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e0d1d0110b4ec421489f.md
new file mode 100644
index 00000000000..5eccfafdc9b
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e0d1d0110b4ec421489f.md
@@ -0,0 +1,269 @@
+---
+id: 62a8e0d1d0110b4ec421489f
+title: Step 112
+challengeType: 0
+dashedName: step-112
+---
+
+# --description--
+
+At the end of your code, create two empty functions named `attack` and `dodge`.
+
+# --hints--
+
+You should use the `function` keyword to declare `attack`.
+
+```js
+assert.match(code, /function\s*attack/);
+```
+
+`attack` should be an empty function.
+
+```js
+assert.match(attack.toString(), /attack\s*\(\s*\)\s*\{\s*\}/);
+```
+
+You should use the `function` keyword to declare `dodge`.
+
+```js
+assert.match(code, /function\s*dodge/);
+```
+
+`dodge` should be an empty function.
+
+```js
+assert.match(dodge.toString(), /dodge\s*\(\s*\)\s*\{\s*\}/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e142f7f0bd4fed898de3.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e142f7f0bd4fed898de3.md
new file mode 100644
index 00000000000..70d0725b1d9
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e142f7f0bd4fed898de3.md
@@ -0,0 +1,288 @@
+---
+id: 62a8e142f7f0bd4fed898de3
+title: Step 113
+challengeType: 0
+dashedName: step-113
+---
+
+# --description--
+
+Add a new object to the end of the `locations` array, following the same properties as the rest of the objects. Set `name` to `fight`, `button text` to an array with `Attack`, `Dodge`, and `Run`, `button functions` to an array with `attack`, `dodge`, and `goTown`, and `text` to `You are fighting a monster.`.
+
+# --hints--
+
+Your `locations` array should have 4 values in it.
+
+```js
+console.log(locations);
+assert.lengthOf(locations, 4);
+```
+
+Your new value should be an object.
+
+```js
+assert.isObject(locations[3]);
+```
+
+Your new object should have a `name` property set to `fight`.
+
+```js
+assert.equal(locations[3].name, "fight");
+```
+
+Your new object should have a `button text` property set to an array with the strings `Attack`, `Dodge`, and `Run`.
+
+```js
+assert.deepEqual(locations[3]["button text"], ["Attack", "Dodge", "Run"]);
+```
+
+Your new object should have a `button functions` property set to an array with the variables `attack`, `dodge`, and `goTown`.
+
+```js
+assert.deepEqual(locations[3]["button functions"], [attack, dodge, goTown]);
+```
+
+Your new object should have a `text` property set to `You are fighting a monster.`.
+
+```js
+assert.equal(locations[3].text, "You are fighting a monster.");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+--fcc-editable-region--
+function goFight() {
+
+}
+--fcc-editable-region--
+
+function attack() {
+
+}
+
+function dodge() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e21398ad61520edb724f.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e21398ad61520edb724f.md
new file mode 100644
index 00000000000..ec221bb2490
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e21398ad61520edb724f.md
@@ -0,0 +1,270 @@
+---
+id: 62a8e21398ad61520edb724f
+title: Step 115
+challengeType: 0
+dashedName: step-115
+---
+
+# --description--
+
+Below your `update` call, set the `monsterHealth` to be the health of the current monster. You can get this value by accessing the `health` property of `monsters[fighting]`.
+
+# --hints--
+
+You should use bracket notation to access the `monsters` array at the `fighting` index.
+
+```js
+assert.match(goFight.toString(), /monsters\[fighting\]/);
+```
+
+You should assign the value of `monsters[fighting]` to the `monsterHealth` variable.
+
+```js
+assert.match(goFight.toString(), /monsterHealth\s*=\s*monsters\[fighting\](\.health|\[('|")health\2\])/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+--fcc-editable-region--
+function goFight() {
+ update(locations[3]);
+
+}
+--fcc-editable-region--
+
+function attack() {
+
+}
+
+function dodge() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e24c673b075317cc0b09.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e24c673b075317cc0b09.md
new file mode 100644
index 00000000000..64379cb2b5d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e24c673b075317cc0b09.md
@@ -0,0 +1,281 @@
+---
+id: 62a8e24c673b075317cc0b09
+title: Step 116
+challengeType: 0
+dashedName: step-116
+---
+
+# --description--
+
+The HTML element that shows the monster's stats has been hidden with CSS. Display the `monsterStats` element by updating the `display` property of the `style` property to `block`. For example, updating the `first` property of the `name` property of `user` would look like:
+
+```js
+user.name.first = "Naomi";
+```
+
+# --hints--
+
+You should use dot notation to access the `style` property of `monsterStats`.
+
+```js
+assert.match(goFight.toString(), /monsterStats\.style/);
+```
+
+You should use dot notation to access the `display` property of the `style` property.
+
+```js
+assert.match(goFight.toString(), /monsterStats\.style\.display/);
+```
+
+You should set the `display` property to `block`.
+
+```js
+assert.match(goFight.toString(), /monsterStats\.style\.display\s*=\s*('|")block\1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+--fcc-editable-region--
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+
+}
+--fcc-editable-region--
+
+function attack() {
+
+}
+
+function dodge() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e271f8e3d1541f9624ad.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e271f8e3d1541f9624ad.md
new file mode 100644
index 00000000000..0ccd9de7c1a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e271f8e3d1541f9624ad.md
@@ -0,0 +1,284 @@
+---
+id: 62a8e271f8e3d1541f9624ad
+title: Step 117
+challengeType: 0
+dashedName: step-117
+---
+
+# --description--
+
+Now set the `innerText` property of `monsterName` to be the `name` property of the current monster. Do the same for `monsterHealthText` and the `health` property.
+
+# --hints--
+
+You should use dot notation to access the `innerText` property of `monsterName`.
+
+```js
+assert.match(goFight.toString(), /monsterName\.innerText/);
+```
+
+You should set the `innerText` property of `monsterName` to be the `name` value of the current monster. Remember that you can get the current monster with `monsters[fighting]`.
+
+```js
+assert.match(goFight.toString(), /monsterName\.innerText\s*=\s*monsters\[fighting\]\.name/);
+```
+
+You should use dot notation to access the `innerText` property of `monsterHealthText`.
+
+```js
+assert.match(goFight.toString(), /monsterHealthText\.innerText/);
+```
+
+You should set the `innerText` property of `monsterHealthText` to be the `health` value of the current monster. Remember that you assigned this value to a `monsterHealth` variable.
+
+```js
+assert.match(goFight.toString(), /monsterHealthText\.innerText\s*=\s*monsterHealth/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+--fcc-editable-region--
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+
+}
+--fcc-editable-region--
+
+function attack() {
+
+}
+
+function dodge() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e35675c18c56354c08cf.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e35675c18c56354c08cf.md
new file mode 100644
index 00000000000..229ca08f2a2
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e35675c18c56354c08cf.md
@@ -0,0 +1,285 @@
+---
+id: 62a8e35675c18c56354c08cf
+title: Step 118
+challengeType: 0
+dashedName: step-118
+---
+
+# --description--
+
+Now you can build the `attack` function. First, update the `text` message to say `The [monster name] attacks.`, replacing `[monster name]` with the name of the monster. Remember you can use the concatenation operator for this.
+
+# --hints--
+
+You should use dot notation to access the `innerText` property of `text`.
+
+```js
+assert.match(attack.toString(), /text\.innerText/);
+```
+
+You should assign the string `The ` to `innerText` property of `text`.
+
+```js
+assert.match(attack.toString(), /text\.innerText\s*=\s*('|")The \1/);
+```
+
+You should use the concatenation operator to add the value of `monsters[fighting].name` to the `The ` string.
+
+```js
+assert.match(attack.toString(), /text\.innerText\s*=\s*('|")The \1\s*\+\s*monsters\[fighting\]\.name/);
+```
+
+You should use the concatenation operator to add the string ` attacks.` to the `monsters[fighting].name` string.
+
+```js
+assert.match(attack.toString(), /text\.innerText\s*=\s*('|")The \1\s*\+\s*monsters\[fighting\]\.name\s*\+\s*('|") attacks\.\2/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+
+}
+--fcc-editable-region--
+
+function dodge() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e41e2f190c58404dd46e.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e41e2f190c58404dd46e.md
new file mode 100644
index 00000000000..6566de3802a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e41e2f190c58404dd46e.md
@@ -0,0 +1,293 @@
+---
+id: 62a8e41e2f190c58404dd46e
+title: Step 119
+challengeType: 0
+dashedName: step-119
+---
+
+# --description--
+
+On a new line, add the string ` You attack it with your [weapon].` to the `text` value, replacing `[weapon]` with the player's current weapon.
+
+# --hints--
+
+You should use dot notation to access the `innerText` property of `text` on a new line.
+
+```js
+const match = attack.toString().match(/text\.innerText/g);
+assert.lengthOf(match, 2);
+```
+
+You should use compound assignment with `text.innerText`.
+
+```js
+assert.match(attack.toString(), /text\.innerText\s*\+=/);
+```
+
+You should add the string ` You attack it with your ` to the `text.innerText` value. Remember that spacing matters.
+
+```js
+assert.match(attack.toString(), /text\.innerText\s*\+=\s*('|") You attack it with your \1/);
+```
+
+You should use the concatenation operator to add the current weapon to the string. You can get the current weapon with `weapons[currentWeapon].name`.
+
+```js
+assert.match(attack.toString(), /text\.innerText\s*\+=\s*('|") You attack it with your \1\s*\+\s*weapons\[currentWeapon\]\.name/);
+```
+
+You should use the concatenation operator to end your string with `.`.
+
+```js
+assert.match(attack.toString(), /text\.innerText\s*\+=\s*('|") You attack it with your \1\s*\+\s*weapons\[currentWeapon\]\.name\s*\+\s*('|")\.\2/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+
+}
+--fcc-editable-region--
+
+function dodge() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e49f4df7af5ae2d7a616.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e49f4df7af5ae2d7a616.md
new file mode 100644
index 00000000000..687f2f04e57
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e49f4df7af5ae2d7a616.md
@@ -0,0 +1,288 @@
+---
+id: 62a8e49f4df7af5ae2d7a616
+title: Step 121
+challengeType: 0
+dashedName: step-121
+---
+
+# --description--
+
+Set `monsterHealth` to `monsterHealth` minus the power of the player's current weapon. Remember you have the `currentWeapon` variable and the `power` property.
+
+# --hints--
+
+You should use compound assignment to modify the `monsterHealth` variable.
+
+```js
+assert.match(attack.toString(), /monsterHealth\s*-=/);
+```
+
+You should use bracket notation with `currentWeapon` to access `weapons`.
+
+```js
+assert.match(attack.toString(), /weapons\[currentWeapon\]/);
+```
+
+You should use dot notation to access the `power` property of `weapons[currentWeapon]`.
+
+```js
+assert.match(attack.toString(), /weapons\[currentWeapon\]\.power/);
+```
+
+You should subtract the `power` of the current weapon from `monsterHealth`.
+
+```js
+assert.match(attack.toString(), /monsterHealth\s*-=\s*weapons\[currentWeapon\]\.power/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+
+}
+--fcc-editable-region--
+
+function dodge() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e4dc6a60f85bf256a0cb.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e4dc6a60f85bf256a0cb.md
new file mode 100644
index 00000000000..fe85bcd7f75
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8e4dc6a60f85bf256a0cb.md
@@ -0,0 +1,316 @@
+---
+id: 62a8e4dc6a60f85bf256a0cb
+title: Step 122
+challengeType: 0
+dashedName: step-122
+---
+
+# --description--
+
+JavaScript offers the built-in `Math` utility which offers a number of mathematical tools. One of those is `Math.random()`, which generates a random number between 0 and 1. Another is `Math.floor()`, which rounds a given number down to the nearest integer.
+
+Using these, you can generate a random number within a range. For example, this generates a random number between 1 and 5: `Math.floor(Math.random() * 5) + 1;`.
+
+Following this pattern, add a random number between one and the value of `xp` at the end of your `monsterHealth` variable change.
+
+# --hints--
+
+You should use the same `monsterHealth` line you already wrote.
+
+```js
+assert.lengthOf(attack.toString().match(/monsterHealth/g), 1);
+```
+
+You should add to the `weapons[currentWeapon].power` value.
+
+```js
+assert.match(attack.toString(), /monsterHealth\s*-=\s*weapons\[currentWeapon\]\.power\s*\+/);
+```
+
+You should use `Math.floor()`.
+
+```js
+assert.match(attack.toString(), /Math\.floor/);
+```
+
+You should use `Math.random()`.
+
+```js
+assert.match(attack.toString(), /Math\.random/);
+```
+
+You should multiply `Math.random()` by the value of `xp`.
+
+```js
+assert.match(attack.toString(), /Math\.random\(\)\s*\*\s*xp/);
+```
+
+You should use `Math.floor()` to round the result of `Math.random() * xp` down.
+
+```js
+assert.match(attack.toString(), /Math\.floor\(\s*Math\.random\(\)\s*\*\s*xp\s*\)/);
+```
+
+You should add `1` to the result of `Math.floor()`.
+
+```js
+assert.match(attack.toString(), /Math\.floor\(\s*Math\.random\(\)\s*\*\s*xp\s*\)\s*\+\s*1/);
+```
+
+You should add the result of `Math.floor(Math.random() * xp) + 1` to the result of `weapons[currentWeapon].power`.
+
+```js
+assert.match(attack.toString(), /monsterHealth\s*-=\s*weapons\[currentWeapon\]\.power\s*\+\s*Math\.floor\(\s*Math\.random\(\)\s*\*\s*xp\s*\)\s*\+\s*1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+
+}
+--fcc-editable-region--
+
+function dodge() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8edd05e27cc668051686f.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8edd05e27cc668051686f.md
new file mode 100644
index 00000000000..acf1efd38b0
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8edd05e27cc668051686f.md
@@ -0,0 +1,285 @@
+---
+id: 62a8edd05e27cc668051686f
+title: Step 124
+challengeType: 0
+dashedName: step-124
+---
+
+# --description--
+
+Add an `if` statement to check if `health` is less than or equal to `0`. If it is, call the `lose` function.
+
+# --hints--
+
+Your `attack` function should have an `if` statement.
+
+```js
+assert.match(attack.toString(), /if/);
+```
+
+Your `if` statement should check if `health` is less than or equal to `0`.
+
+```js
+assert.match(attack.toString(), /if\s*\(health\s*<=\s*0\)/);
+```
+
+Your `if` statement should call the `lose` function.
+
+```js
+assert.match(attack.toString(), /lose\(\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+
+}
+--fcc-editable-region--
+
+function dodge() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ee154c8946678775c4a4.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ee154c8946678775c4a4.md
new file mode 100644
index 00000000000..ac058ac03bc
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8ee154c8946678775c4a4.md
@@ -0,0 +1,297 @@
+---
+id: 62a8ee154c8946678775c4a4
+title: Step 125
+challengeType: 0
+dashedName: step-125
+---
+
+# --description--
+
+You can make an `else` statement conditional by using `else if`. At the end of your `if` statement, add an `else if` statement to check if `monsterHealth` is less than or equal to `0`. In your `else if`, call the `defeatMonster` function.
+
+Here's an example:
+
+```js
+if (num > 10) {
+
+} else if (num < 5) {
+
+}
+```
+
+# --hints--
+
+You should have an `else if` statement.
+
+```js
+assert.match(attack.toString(), /else if/);
+```
+
+Your `else if` statement should check if `monsterHealth` is less than or equal to `0`.
+
+```js
+assert.match(attack.toString(), /else\s*if\s*\(\s*monsterHealth\s*<=\s*0\s*\)/);
+```
+
+Your `else if` statement should call the `defeatMonster` function.
+
+```js
+assert.match(attack.toString(), /else\s*if\s*\(\s*monsterHealth\s*<=\s*0\s*\)\s*\{\s*defeatMonster/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ defeatMonster();
+ }
+}
+
+function dodge() {
+
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8eec45f77bc69e8775294.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8eec45f77bc69e8775294.md
new file mode 100644
index 00000000000..3524f53b4a3
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8eec45f77bc69e8775294.md
@@ -0,0 +1,291 @@
+---
+id: 62a8eec45f77bc69e8775294
+title: Step 127
+challengeType: 0
+dashedName: step-127
+---
+
+# --description--
+
+Inside the `dodge` function, set `text.innerText` equal to the string `You dodge the attack from the [monster]`. Replace `[monster]` with the name of the monster, using the `name` property.
+
+# --hints--
+
+You should assign the string `You dodge the attack from the ` to the `text.innerText` property. Remember that spacing matters.
+
+```js
+assert.match(dodge.toString(), /text\.innerText\s*=\s*('|")You dodge the attack from the \1/);
+```
+
+You should use the concatenation operator to add the name of the monster to the end of the string. You can get this with `monster[fighting].name`.
+
+```js
+assert.match(dodge.toString(), /text\.innerText\s*=\s*('|")You dodge the attack from the \1\s*\+\s*monsters\[fighting\]\.name/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ defeatMonster();
+ }
+}
+
+--fcc-editable-region--
+function dodge() {
+
+}
+--fcc-editable-region--
+
+function defeatMonster() {
+
+}
+
+function lose() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8eefe2e68b66ac563816b.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8eefe2e68b66ac563816b.md
new file mode 100644
index 00000000000..f67c008aa05
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8eefe2e68b66ac563816b.md
@@ -0,0 +1,299 @@
+---
+id: 62a8eefe2e68b66ac563816b
+title: Step 128
+challengeType: 0
+dashedName: step-128
+---
+
+# --description--
+
+In your `defeatMonster` function, set `gold` equal to `gold` plus the monster's level times `6.7`. You can get the monster's level with the `level` property.
+
+Here is an example of setting `num` to `num` plus `5` * `8`: `num += 5 * 8`. Use `Math.floor()` to round the result down.
+
+# --hints--
+
+You should use compound assignment to modify `gold`.
+
+```js
+assert.match(defeatMonster.toString(), /gold\s*\+=/);
+```
+
+You should use `Math.floor()` to round the result of the monster's level times `6.7`.
+
+```js
+assert.match(defeatMonster.toString(), /Math\.floor\(\s*monsters\[fighting\]\.level\s*\*\s*6\.7\s*\)/);
+```
+
+You should add the result of `Math.floor(gold + monsters[fighting].level * 6.7)` to `gold`.
+
+```js
+assert.match(defeatMonster.toString(), /gold\s*\+=\s*Math\.floor\(\s*monsters\[fighting\]\.level\s*\*\s*6\.7\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ defeatMonster();
+ }
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+--fcc-editable-region--
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+
+}
+--fcc-editable-region--
+
+function lose() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8eff21c0b0f6ebe5b8e38.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8eff21c0b0f6ebe5b8e38.md
new file mode 100644
index 00000000000..dd0068655fd
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8eff21c0b0f6ebe5b8e38.md
@@ -0,0 +1,319 @@
+---
+id: 62a8eff21c0b0f6ebe5b8e38
+title: Step 132
+challengeType: 0
+dashedName: step-132
+---
+
+# --description--
+
+Your `locations` array doesn't have a fifth element, so `locations[4]` doesn't work. Add a new object at the end of the `locations` array, following the same structure as the other objects. Set `name` to `kill monster`, set `button text` to an array with three `Go to town square` strings, set `button functions` to an array with three `goTown` variables, and set `text` to `The monster screams Arg! as it dies. You gain experience points and find gold.`.
+
+# --hints--
+
+Your `locations` array should have five values.
+
+```js
+assert.lengthOf(locations, 5);
+```
+
+Your fifth `locations` value should be an object.
+
+```js
+assert.isObject(locations[4]);
+```
+
+Your fifth `locations` value should have a `name` property with the value `kill monster`.
+
+```js
+assert.equal(locations[4].name, 'kill monster');
+```
+
+Your fifth `locations` value should have a `button text` property with the value an array with three `Go to town square` strings.
+
+```js
+assert.deepEqual(locations[4]["button text"], ['Go to town square', 'Go to town square', 'Go to town square']);
+```
+
+Your fifth `locations` value should have a `button functions` property with the value an array with three `goTown` variables.
+
+```js
+assert.deepEqual(locations[4]["button functions"], [goTown, goTown, goTown]);
+```
+
+Your fifth `locations` value should have a `text` property with the value `The monster screams Arg! as it dies. You gain experience points and find gold.`.
+
+```js
+assert.equal(locations[4].text, 'The monster screams Arg! as it dies. You gain experience points and find gold.');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+--fcc-editable-region--
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ }
+];
+--fcc-editable-region--
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ defeatMonster();
+ }
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f06fb318666fef69f91e.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f06fb318666fef69f91e.md
new file mode 100644
index 00000000000..ad30c67858d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f06fb318666fef69f91e.md
@@ -0,0 +1,301 @@
+---
+id: 62a8f06fb318666fef69f91e
+title: Step 133
+challengeType: 0
+dashedName: step-133
+---
+
+# --description--
+
+The word `Arg!` should have quotes around it. Besides escaping quotes, there is another way you can include quotation marks inside a string. Change the double quotes around the string `The monster screams Arg! as it dies. You gain experience points and find gold.` to single quotes `'`, then add double quotes around `Arg!`.
+
+# --hints--
+
+You should use single quotes around the string.
+
+```js
+assert.match(code, /'The monster screams "?Arg!"? as it dies. You gain experience points and find gold.'/);
+```
+
+You should use double quotes around `Arg!`.
+
+```js
+assert.equal(locations[4].text, 'The monster screams "Arg!" as it dies. You gain experience points and find gold.');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+--fcc-editable-region--
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: "The monster screams Arg! as it dies. You gain experience points and find gold."
+ }
+--fcc-editable-region--
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ defeatMonster();
+ }
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f14fe6d1fc72454648c7.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f14fe6d1fc72454648c7.md
new file mode 100644
index 00000000000..ee850581fa7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f14fe6d1fc72454648c7.md
@@ -0,0 +1,308 @@
+---
+id: 62a8f14fe6d1fc72454648c7
+title: Step 134
+challengeType: 0
+dashedName: step-134
+---
+
+# --description--
+
+After a monster is defeated, the monster's stat box should no longer display. On the first line of the `update` function, use `monsterStats.style.display` to change the `display` value to `none`.
+
+# --hints--
+
+You should use `monsterStats.style.display` in the `update` function.
+
+```js
+assert.match(update.toString(), /monsterStats\.style\.display/);
+```
+
+You should set `monsterStats.style.display` to `none`.
+
+```js
+assert.match(update.toString(), /monsterStats\.style\.display\s*=\s*('|")none\1/);
+```
+
+This should be the first line of the `update` function.
+
+```js
+assert.match(update.toString(), /update\s*\(\s*location\s*\)\s*\{\s*monsterStats\.style\.display\s*=\s*('|")none\1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+--fcc-editable-region--
+function update(location) {
+
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+--fcc-editable-region--
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ defeatMonster();
+ }
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f1d5f5ddbf74c07f733b.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f1d5f5ddbf74c07f733b.md
new file mode 100644
index 00000000000..de99851e153
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f1d5f5ddbf74c07f733b.md
@@ -0,0 +1,296 @@
+---
+id: 62a8f1d5f5ddbf74c07f733b
+title: Step 135
+challengeType: 0
+dashedName: step-135
+---
+
+# --description--
+
+In the `lose` function, call the `update` function and pass in the sixth object of your `locations` array. Note that you haven't created this object just yet.
+
+# --hints--
+
+Test 1
+
+```js
+
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ defeatMonster();
+ }
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+--fcc-editable-region--
+function lose() {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f20463b324759953edad.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f20463b324759953edad.md
new file mode 100644
index 00000000000..097ae332be3
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f20463b324759953edad.md
@@ -0,0 +1,356 @@
+---
+id: 62a8f20463b324759953edad
+title: Step 136
+challengeType: 0
+dashedName: step-136
+---
+
+# --description--
+
+At the end of your code, create a `restart` function. Inside this function, set `xp` to `0`, `health` to `100`, `gold` to `50`, `currentWeapon` to `0`, and set `inventory` to an array with the string `stick`.
+
+Also update the `innerText` properties of `goldText`, `healthText`, and `xpText` to their current values.
+
+Finally, call the `goTown()` function.
+
+# --hints--
+
+You should use the `function` keyword to declare `restart`.
+
+```js
+assert.match(code, /function\s+restart/);
+```
+
+Your `restart` function should set `xp` to `0`.
+
+```js
+assert.match(restart.toString(), /xp\s*=\s*0/);
+```
+
+Your `restart` function should set `health` to `100`.
+
+```js
+assert.match(restart.toString(), /health\s*=\s*100/);
+```
+
+Your `restart` function should set `gold` to `50`.
+
+```js
+assert.match(restart.toString(), /gold\s*=\s*50/);
+```
+
+Your `restart` function should set `currentWeapon` to `0`.
+
+```js
+assert.match(restart.toString(), /currentWeapon\s*=\s*0/);
+```
+
+Your `restart` function should set `inventory` to an array with the string `stick`.
+
+```js
+assert.match(restart.toString(), /inventory\s*=\s*\[\s*('|")stick\1\s*\]/);
+```
+
+Your `restart` function should call the `goTown()` function.
+
+```js
+assert.match(restart.toString(), /goTown\(\)/);
+```
+
+You should set `goldText.innerText` to the value of `gold`.
+
+```js
+assert.match(restart.toString(), /goldText\.innerText\s*=\s*gold/);
+```
+
+You should set `healthText.innerText` to the value of `health`.
+
+```js
+assert.match(restart.toString(), /healthText\.innerText\s*=\s*health/);
+```
+
+You should set `xpText.innerText` to the value of `xp`.
+
+```js
+assert.match(restart.toString(), /xpText\.innerText\s*=\s*xp/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ defeatMonster();
+ }
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f256b813a476cae51f49.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f256b813a476cae51f49.md
new file mode 100644
index 00000000000..84ad6a8fbc2
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f256b813a476cae51f49.md
@@ -0,0 +1,353 @@
+---
+id: 62a8f256b813a476cae51f49
+title: Step 138
+challengeType: 0
+dashedName: step-138
+---
+
+# --description--
+
+Back to your `attack` function - inside the `else if` block, create another `if` and `else` statement. If the player is fighting the dragon (`fighting` would be `2`), call the `winGame` function. Move the `defeatMonster()` call to the `else` block.
+
+Here is an example that checks if `num` is equal to `5`:
+
+```js
+if (num === 5) {
+
+} else {
+
+}
+```
+
+# --hints--
+
+You should add a new `if` statement in your `else if` block.
+
+```js
+const block = attack.toString().split("else if");
+assert.include(block[1], "if");
+```
+
+Your new `if` statement should check if `fighting` is equal to `2`.
+
+```js
+const block = attack.toString().split("else if");
+assert.match(block[1], /if\s*\(\s*fighting\s*===\s*2\s*\)/);
+```
+
+You should call the `winGame` function in your `if` block.
+
+```js
+const block = attack.toString().split("else if");
+assert.match(block[1], /if\s*\(\s*fighting\s*===\s*2\s*\)\s*\{\s*winGame\(\)/);
+```
+
+You should add an `else` block.
+
+```js
+const block = attack.toString().split("else if");
+assert.include(block[1], "else");
+```
+
+Your `else` block should call the `defeatMonster` function.
+
+```js
+const block = attack.toString().split("else if");
+assert.match(block[1], /else\s*\{\s*defeatMonster\(\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ defeatMonster();
+ }
+}
+--fcc-editable-region--
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f2bc37675e77d5835235.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f2bc37675e77d5835235.md
new file mode 100644
index 00000000000..cd564871491
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a8f2bc37675e77d5835235.md
@@ -0,0 +1,355 @@
+---
+id: 62a8f2bc37675e77d5835235
+title: Step 139
+challengeType: 0
+dashedName: step-139
+---
+
+# --description--
+
+JavaScript has a conditional operator called the ternary operator. This can be used as a one-line `if-else` expression. The syntax is: `condition ? true : false`.
+
+Here is an example of an `if-else` expression changed to a ternary:
+
+```js
+if (num > 5) {
+ bigger()
+} else {
+ smaller()
+}
+
+num > 5 ? bigger() : smaller();
+```
+
+Change your new `if-else` expression to a ternary.
+
+# --hints--
+
+You should remove the `if` and `else` from your `else if` block.
+
+```js
+const block = attack.toString().split("else if");
+assert.notMatch(block[1], /if/);
+assert.notMatch(block[1], /else/);
+```
+
+You should check if `fighting` is equal to `2`.
+
+```js
+const block = attack.toString().split("else if");
+assert.match(block[1], /fighting\s*===\s*2/);
+```
+
+Using the ternary syntax, you should call `winGame` if `fighting` is equal to `2`.
+
+```js
+const block = attack.toString().split("else if");
+assert.match(block[1], /fighting\s*===\s*2\s*\?\s*winGame\(\)/);
+```
+
+Using the ternary syntax, you should call `defeatMonster` if `fighting` is not equal to `2`.
+
+```js
+const block = attack.toString().split("else if");
+assert.match(block[1], /fighting\s*===\s*2\s*\?\s*winGame\(\)\s*\:\s*defeatMonster\(\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a94114ce0b8918b487390f.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a94114ce0b8918b487390f.md
new file mode 100644
index 00000000000..8522ebd7445
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62a94114ce0b8918b487390f.md
@@ -0,0 +1,348 @@
+---
+id: 62a94114ce0b8918b487390f
+title: Step 141
+challengeType: 0
+dashedName: step-141
+---
+
+# --description--
+
+Add another object in the `locations` array. Everything should be the same as the `lose` object, except the `name` should be `win` and the `text` should be `You defeat the dragon! YOU WIN THE GAME! 🎉`.
+
+# --hints--
+
+You should have seven values in the `locations` array.
+
+```js
+assert.lengthOf(locations, 7);
+```
+
+Your seventh `locations` value should be an object.
+
+```js
+assert.isObject(locations[6]);
+```
+
+Your seventh `locations` value should have a `name` property with the value `win`.
+
+```js
+assert.equal(locations[6].name, 'win');
+```
+
+Your seventh `locations` value should have a `button text` property with the value an array with three `REPLAY?` strings.
+
+```js
+assert.deepEqual(locations[6]["button text"], ['REPLAY?', 'REPLAY?', 'REPLAY?']);
+```
+
+Your seventh `locations` value should have a `button functions` property with the value an array with three `restart` variables.
+
+```js
+assert.deepEqual(locations[6]["button functions"], [restart, restart, restart]);
+```
+
+Your seventh `locations` value should have a `text` property with the value `You defeat the dragon! YOU WIN THE GAME! 🎉`.
+
+```js
+assert.equal(locations[6].text, 'You defeat the dragon! YOU WIN THE GAME! 🎉');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+--fcc-editable-region--
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ }
+--fcc-editable-region--
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1cea594f152ba626b872.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1cea594f152ba626b872.md
new file mode 100644
index 00000000000..d38e7a2c1e2
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1cea594f152ba626b872.md
@@ -0,0 +1,326 @@
+---
+id: 62aa1cea594f152ba626b872
+title: Step 142
+challengeType: 0
+dashedName: step-142
+---
+
+# --description--
+
+Your game could be complete now, but you can also make it more interesting.
+
+Inside your `attack` function, change your `health -= monsters[fighting].level;` line to `health -= getMonsterAttackValue(monsters[fighting].level);`. This sets `health` equal to `health` minus the return value of the `getMonsterAttackValue` function, and passes the `level` of the monster as an argument.
+
+# --hints--
+
+You should update your `health` line to be `health -= getMonsterAttackValue(monsters[fighting].level);`.
+
+```js
+assert.match(attack.toString(), /health\s*-=\s*getMonsterAttackValue\(monsters\[fighting\].level\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1d9f535e102e4663e7a6.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1d9f535e102e4663e7a6.md
new file mode 100644
index 00000000000..62f2bd62862
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1d9f535e102e4663e7a6.md
@@ -0,0 +1,342 @@
+---
+id: 62aa1d9f535e102e4663e7a6
+title: Step 144
+challengeType: 0
+dashedName: step-144
+---
+
+# --description--
+
+The attack of the monster will be based on the monster's `level` and the player's `xp`. In the `getMonsterAttackValue` function, use `const` to create a variable called `hit`. Assign it the equation `(level * 5) - (Math.floor(Math.random() * xp));`.
+
+This will set the monster's attack to five times their `level` minus a random number between 0 and the player's `xp`.
+
+# --hints--
+
+You should use `const` to declare the variable `hit`.
+
+```js
+assert.match(code, /const\s*hit/);
+```
+
+You should use the equation `(level * 5) - (Math.floor(Math.random() * xp))`.
+
+```js
+assert.match(getMonsterAttackValue, /(level\s*\*\s*5)\s*-\s*(Math.floor\(Math.random\(\)\s*\*\s*xp\))/);
+```
+
+You should set `hit` to the value of `(level * 5) - (Math.floor(Math.random() * xp))`.
+
+```js
+assert.match(code, /hit\s*=\s*\(level\s*\*\s*5\)\s*-\s*\(Math.floor\(Math.random\(\)\s*\*\s*xp\)\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+}
+
+--fcc-editable-region--
+function getMonsterAttackValue(level) {
+
+}
+--fcc-editable-region--
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1e3c7c3d552fb04f0f18.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1e3c7c3d552fb04f0f18.md
new file mode 100644
index 00000000000..0e1f69267c5
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1e3c7c3d552fb04f0f18.md
@@ -0,0 +1,328 @@
+---
+id: 62aa1e3c7c3d552fb04f0f18
+title: Step 145
+challengeType: 0
+dashedName: step-145
+---
+
+# --description--
+
+Log the value of `hit` to the console to use in debugging. Remember that you can do this with `console.log()`.
+
+# --hints--
+
+You should use the `console.log()` function to log the value of `hit`.
+
+```js
+assert.match(getMonsterAttackValue.toString(), /console\.log\(\s*hit\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+}
+
+--fcc-editable-region--
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+}
+--fcc-editable-region--
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1e8ccd579330e097ce44.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1e8ccd579330e097ce44.md
new file mode 100644
index 00000000000..bcc2b14ee5a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1e8ccd579330e097ce44.md
@@ -0,0 +1,338 @@
+---
+id: 62aa1e8ccd579330e097ce44
+title: Step 146
+challengeType: 0
+dashedName: step-146
+---
+
+# --description--
+
+Functions run specific blocks of code when they are called, but they can also return a value. This value can be assigned to a variable and used elsewhere in your code.
+
+Use the `return` keyword to return the value of `hit` at the end of the function.
+
+# --hints--
+
+You should use the `return` keyword to return the value of `hit`.
+
+```js
+assert.match(getMonsterAttackValue, /return\s*hit/);
+```
+
+Your function should return the expected value.
+
+```js
+xp = 0;
+assert.equal(getMonsterAttackValue(1), 5);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+}
+
+--fcc-editable-region--
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+}
+--fcc-editable-region--
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1eec891ed731db227a36.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1eec891ed731db227a36.md
new file mode 100644
index 00000000000..725aa7e720a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1eec891ed731db227a36.md
@@ -0,0 +1,350 @@
+---
+id: 62aa1eec891ed731db227a36
+title: Step 147
+challengeType: 0
+dashedName: step-147
+---
+
+# --description--
+
+If you play the game in its current state you might notice a bug. If your `xp` is high enough, the `getMonsterAttackValue` function will return a negative number, which will actually add to your total health when fighting a monster!
+
+In `getMonsterAttackValue`, change `return hit` to a ternary operator that returns `hit` if `hit` is greater than `0`, or returns `0` if it is not.
+
+Here is an example of returning a value based on `condition` with a ternary:
+
+```js
+return condition ? true : false;
+```
+
+# --hints--
+
+You should use a ternary to change the `return` value if `hit` is greater than `0`.
+
+```js
+assert.match(getMonsterAttackValue.toString(), /return\s+hit\s*>\s*0/);
+```
+
+You should use a ternary to return `hit` if `hit` is greater than `0`
+
+```js
+assert.match(getMonsterAttackValue.toString(), /return\s+hit\s*>\s*0\s*\?\s*hit/);
+```
+
+You should use a ternary to return `0` if `hit` is not greater than `0`.
+
+```js
+assert.match(getMonsterAttackValue.toString(), /return\s+hit\s*>\s*0\s*\?\s*hit\s*:\s*0/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+
+ }
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+}
+--fcc-editable-region--
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa20e9cf1be9358f5aceae.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa20e9cf1be9358f5aceae.md
new file mode 100644
index 00000000000..88836e37794
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa20e9cf1be9358f5aceae.md
@@ -0,0 +1,338 @@
+---
+id: 62aa20e9cf1be9358f5aceae
+title: Step 150
+challengeType: 0
+dashedName: step-150
+---
+
+# --description--
+
+Add an `else` statement to your `if` statement. In the `else` statement, use the `+=` operator to add the text ` You miss.` to the end of `text.innerText`.
+
+# --hints--
+
+You should add an `else` block after your `if (isMonsterHit())` block.
+
+```js
+assert.match(attack.toString(), /if\s*\(isMonsterHit\(\)\s*\)\s*\{\s*monsterHealth\s*-=\s*weapons\[currentWeapon\]\.power\s*\+\s*Math\.floor\(Math\.random\(\)\s*\*\s*xp\)\s*\+\s*1;\s*\}\s*else/)
+```
+
+You should add the text ` You miss.` to the end of `text.innerText`. Remember to use compound assignment.
+
+```js
+assert.match(attack.toString(), /if\s*\(isMonsterHit\(\)\s*\)\s*\{\s*monsterHealth\s*-=\s*weapons\[currentWeapon\]\.power\s*\+\s*Math\.floor\(Math\.random\(\)\s*\*\s*xp\)\s*\+\s*1;\s*\}\s*else\s*\{\s*text\.innerText\s*\+=\s*('|")\sYou miss\.\1/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+}
+--fcc-editable-region--
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2136fc49b836dfedb959.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2136fc49b836dfedb959.md
new file mode 100644
index 00000000000..7a5d427b22f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2136fc49b836dfedb959.md
@@ -0,0 +1,342 @@
+---
+id: 62aa2136fc49b836dfedb959
+title: Step 151
+challengeType: 0
+dashedName: step-151
+---
+
+# --description--
+
+Now create the `isMonsterHit` function. This will return a boolean value (true or false) to be used in your `if` statement. Return the result of the comparison `Math.random() > .2`.
+
+# --hints--
+
+You should use the `function` keyword to declare `isMonsterHit`.
+
+```js
+assert.match(code, /function\s+isMonsterHit/);
+```
+
+Your `isMonsterHit` function should return the result of the comparison `Math.random() > .2`.
+
+```js
+assert.match(isMonsterHit.toString(), /return\s*Math\.random\(\)\s*>\s*0?\.2/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa21971e3b743844849985.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa21971e3b743844849985.md
new file mode 100644
index 00000000000..2db80762083
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa21971e3b743844849985.md
@@ -0,0 +1,354 @@
+---
+id: 62aa21971e3b743844849985
+title: Step 152
+challengeType: 0
+dashedName: step-152
+---
+
+# --description--
+
+The player should hit if either `Math.random() > .2` **or** if the player's health is less than 20. At the end of your `return` statement, use the logical or operator `||` and check if `health` is less than `20`.
+
+The logical or operator will use the first value if it is truthy, otherwise it will use the second value.
+
+For example: `num < 10 || num > 20`.
+
+# --hints--
+
+Your `isMonsterHit` function should use the logical or operator.
+
+```js
+assert.match(isMonsterHit.toString(), /\|\|/);
+```
+
+Your logical or operator should use `health < 20` as the fallback value.
+
+```js
+assert.match(isMonsterHit.toString(), /\|\|\s*health\s*<\s*20/);
+```
+
+Your function should return the result of the comparison `Math.random() > .2` **or** `health < 20`.
+
+```js
+assert.match(isMonsterHit.toString(), /return\s*Math\.random\(\)\s*>\s*0?\.2\s*\|\|\s*health\s*<\s*20/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+
+}
+--fcc-editable-region--
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa226207f33d3ad4c6f546.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa226207f33d3ad4c6f546.md
new file mode 100644
index 00000000000..4210b69f7a8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa226207f33d3ad4c6f546.md
@@ -0,0 +1,367 @@
+---
+id: 62aa226207f33d3ad4c6f546
+title: Step 154
+challengeType: 0
+dashedName: step-154
+---
+
+# --description--
+
+Use the `+=` operator to add ` Your [weapon] breaks.` to the end of `text.innerText`, replacing `weapon` with the last item in the `inventory` array. You can get this last item by using `inventory.pop()`, which will remove the last item in the array AND return it so it appears in your string.
+
+# --hints--
+
+You should use the compound assignment operator to modify `text.innerText`.
+
+```js
+const concat = attack.toString().match(/\+=/g);
+assert.lengthOf(concat, 3);
+```
+
+You should use the `pop` method on the `inventory` array.
+
+```js
+assert.match(attack.toString(), /inventory\.pop\(\)/);
+```
+
+You should add the string " Your " to `text.innerText`. Remember that spacing matters.
+
+```js
+assert.match(attack.toString(), /text\.innerText\s*\+=\s*('|")\sYour\s\1/);
+```
+
+You should add the return value of `inventory.pop()` to the ` Your ` string.
+
+```js
+console.log(attack.toString());
+assert.match(attack.toString(), /text\.innerText\s*\+=\s*('|")\sYour\s\1\s*\+\s*inventory\.pop\(\)/);
+```
+
+You should add ` breaks.` to the ` "Your " + inventory.pop()` string.
+
+```js
+assert.match(attack.toString(), /text\.innerText\s*\+=\s*('|")\sYour\s\1\s*\+\s*inventory\.pop\(\)\s*\+\s*('|")\sbreaks\.\2/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1) {
+
+ }
+}
+--fcc-editable-region--
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa22aba186563bcbf2c395.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa22aba186563bcbf2c395.md
new file mode 100644
index 00000000000..44980b592f0
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa22aba186563bcbf2c395.md
@@ -0,0 +1,350 @@
+---
+id: 62aa22aba186563bcbf2c395
+title: Step 155
+challengeType: 0
+dashedName: step-155
+---
+
+# --description--
+
+Remember that the increment operator `++` can be used to increase a variable's value by 1. There is also a decrement operator `--` that can be used to decrease a variable's value by 1.
+
+Decrement the value of `currentWeapon` in your `if` statement, after you update the text.
+
+# --hints--
+
+You should use the decrement operator.
+
+```js
+assert.match(attack.toString(), /--/);
+```
+
+You should decrement `currentWeapon` in your `if` statement.
+
+```js
+assert.match(attack.toString(), /currentWeapon\s*--/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+
+ }
+}
+--fcc-editable-region--
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa234322d4ad3e8bce42cc.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa234322d4ad3e8bce42cc.md
new file mode 100644
index 00000000000..65fc9cd5576
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa234322d4ad3e8bce42cc.md
@@ -0,0 +1,364 @@
+---
+id: 62aa234322d4ad3e8bce42cc
+title: Step 156
+challengeType: 0
+dashedName: step-156
+---
+
+# --description--
+
+We don't want a player's only weapon to break. The logical or operator checks if two statements are true.
+
+Use the logical and operator `&&` to add a second condition to your `if` statement. The player's weapon should only break if `inventory.length` does not equal (`!==`) one.
+
+Here is an example of an `if` statement with two conditions:
+
+```js
+if (firstName === "Quincy" && lastName === "Larson") {
+
+}
+```
+
+# --hints--
+
+You should not modify your existing `if` statement.
+
+```js
+assert.match(attack.toString(), /if\s*\(Math\.random\(\)\s*\<=\s*\.1/);
+```
+
+You should use the logical and operator `&&`.
+
+```js
+assert.match(attack.toString(), /if\s*\(Math\.random\(\)\s*\<=\s*\.1\s*&&/);
+```
+
+You should use the logical and operator to check if `inventory.length` does not equal `1`.
+
+```js
+assert.match(attack.toString(), /if\s*\(Math\.random\(\)\s*\<=\s*\.1\s*&&\s*inventory\.length\s*\!\=\=\s*1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+--fcc-editable-region--
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+--fcc-editable-region--
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2469c77b363fdb4f0e06.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2469c77b363fdb4f0e06.md
new file mode 100644
index 00000000000..10cb8603022
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2469c77b363fdb4f0e06.md
@@ -0,0 +1,358 @@
+---
+id: 62aa2469c77b363fdb4f0e06
+title: Step 157
+challengeType: 0
+dashedName: step-157
+---
+
+# --description--
+
+Now you can add a small easter egg (hidden feature) to your game.
+
+Create a new function called `easterEgg` which calls the `update` function with `locations[7]` as the argument.
+
+# --hints--
+
+You should use the `function` keyword to declare `easterEgg`.
+
+```js
+assert.match(code, /function\s+easterEgg\s*/);
+```
+
+`easterEgg` should call the `update` function.
+
+```js
+assert.match(easterEgg.toString(), /update\(/);
+```
+
+`easterEgg` should call the `update` function with `locations[7]` as the argument.
+
+```js
+assert.match(easterEgg.toString(), /update\(\s*locations\[7\]\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa258da314ef42ba0a1858.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa258da314ef42ba0a1858.md
new file mode 100644
index 00000000000..5f657de3877
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa258da314ef42ba0a1858.md
@@ -0,0 +1,384 @@
+---
+id: 62aa258da314ef42ba0a1858
+title: Step 159
+challengeType: 0
+dashedName: step-159
+---
+
+# --description--
+
+Create two new functions named `pickTwo` and `pickEight`.
+
+Inside each of those, call the `pick()` function and pass either `2` or `8` as the argument depending on the function name.
+
+# --hints--
+
+You should use the `function` keyword to declare `pickTwo`.
+
+```js
+assert.match(code, /function\s+pickTwo\s*/);
+```
+
+You should use the `function` keyword to declare `pickEight`.
+
+```js
+assert.match(code, /function\s+pickEight\s*/);
+```
+
+`pickTwo` should call the `pick` function.
+
+```js
+assert.match(pickTwo.toString(), /pick\(/);
+```
+
+`pickTwo` should call the `pick` function with `2` as the argument.
+
+```js
+assert.match(pickTwo.toString(), /pick\(\s*2\s*\)/);
+```
+
+`pickEight` should call the `pick` function.
+
+```js
+assert.match(pickEight.toString(), /pick\(/);
+```
+
+`pickEight` should call the `pick` function with `8` as the argument.
+
+```js
+assert.match(pickEight.toString(), /pick\(\s*8\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+function pick(guess) {
+
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa25fcb5837d43b4d9873d.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa25fcb5837d43b4d9873d.md
new file mode 100644
index 00000000000..01f3692b24e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa25fcb5837d43b4d9873d.md
@@ -0,0 +1,389 @@
+---
+id: 62aa25fcb5837d43b4d9873d
+title: Step 160
+challengeType: 0
+dashedName: step-160
+---
+
+# --description--
+
+Add another object to your `locations` array. Set `name` to `easter egg`, set `button text` to an array with the strings `2`, `8`, and `Go to town square?`, set `button functions` to an array with the variables `pickTwo`, `pickEight`, and `goTown`, and `text` to `You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!`.
+
+# --hints--
+
+Your `locations` array should have 8 values.
+
+```js
+assert.lengthOf(locations, 8);
+```
+
+Your eighth `locations` value should be an object.
+
+```js
+assert.isObject(locations[7]);
+```
+
+Your eighth `locations` value should have a `name` property with the value `easter egg`.
+
+```js
+assert.equal(locations[7].name, "easter egg");
+```
+
+Your eighth `locations` value should have a `button text` property with the value an array with the strings `2`, `8`, and `Go to town square?`.
+
+```js
+assert.deepEqual(locations[7]["button text"], ["2", "8", "Go to town square?"]);
+```
+
+Your eighth `locations` value should have a `button functions` property with the value an array with the variables `pickTwo`, `pickEight`, and `goTown`.
+
+```js
+assert.deepEqual(locations[7]["button functions"], [pickTwo, pickEight, goTown]);
+```
+
+Your eighth `locations` value should have a `text` property with the value `You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!`.
+
+```js
+assert.equal(locations[7].text, "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa264d23cdaa45a20efada.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa264d23cdaa45a20efada.md
new file mode 100644
index 00000000000..b043a04a1a5
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa264d23cdaa45a20efada.md
@@ -0,0 +1,381 @@
+---
+id: 62aa264d23cdaa45a20efada
+title: Step 162
+challengeType: 0
+dashedName: step-162
+---
+
+# --description--
+
+After your `numbers` array, create a `while` loop. A while loop accepts a condition, and will run the code in the block until the condition is no longer true.
+
+Your `while` loop should run while `numbers.length` is less than `10`.
+
+Here is an example of a `while` loop that runs while `i` is less than five.
+
+```js
+while (i < 5) {
+
+}
+```
+
+# --hints--
+
+Your `pick` function should have a `while` loop.
+
+```js
+assert.match(pick.toString(), /while\s*\(/);
+```
+
+Your `while` loop should run while `numbers.length < 10`.
+
+```js
+assert.match(pick.toString(), /while\s*\(\s*numbers.length\s*<\s*10\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa26cca3cd3d46c431e73b.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa26cca3cd3d46c431e73b.md
new file mode 100644
index 00000000000..beace6c6228
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa26cca3cd3d46c431e73b.md
@@ -0,0 +1,379 @@
+---
+id: 62aa26cca3cd3d46c431e73b
+title: Step 163
+challengeType: 0
+dashedName: step-163
+---
+
+# --description--
+
+Inside your `while` loop, push a random number between 0 and 10 to the end of the `numbers` array. You can create this random number with `Math.floor(Math.random() * 11)`.
+
+# --hints--
+
+You should use the `push` method to add a random number to the end of the `numbers` array.
+
+```js
+assert.match(pick.toString(), /numbers\.push\(/);
+```
+
+You should use `Math.floor(Math.random() * 11)` to create the random number.
+
+```js
+assert.match(pick.toString(), /Math\.floor\(Math\.random\(\)\s*\*\s*11\s*\)/);
+```
+
+You should `push` the result of `Math.floor(Math.random() * 11)` to the end of the `numbers` array.
+
+```js
+assert.match(pick.toString(), /numbers\.push\(\s*Math\.floor\(Math\.random\(\)\s*\*\s*11\s*\)\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa27227399d647e1c37a3c.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa27227399d647e1c37a3c.md
new file mode 100644
index 00000000000..ac85513b88f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa27227399d647e1c37a3c.md
@@ -0,0 +1,380 @@
+---
+id: 62aa27227399d647e1c37a3c
+title: Step 164
+challengeType: 0
+dashedName: step-164
+---
+
+# --description--
+
+After the `while` loop, set `text.innerText` to equal `You picked [guess]. Here are the random numbers:`. Replace `guess` with the player's guess.
+
+# --hints--
+
+You should set `text.innerText` to the string `You picked `. Remember that spacing matters.
+
+```js
+assert.match(pick.toString(), /text\.innerText\s*=\s*('|")You picked \1/);
+```
+
+You should use the concatenation operator to add the value of the `guess` parameter to your `You picked ` string.
+
+```js
+assert.match(pick.toString(), /text\.innerText\s*=\s*('|")You picked \1\s*\+\s*guess/);
+```
+
+You should use the concatenation operator to add the string `. Here are the random numbers:` to your `"You picked " + guess` string.
+
+```js
+assert.match(pick.toString(), /text\.innerText\s*=\s*('|")You picked \1\s*\+\s*guess\s*\+\s*('|")\.\sHere are the random numbers:\2/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa27560def7048d7b4a095.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa27560def7048d7b4a095.md
new file mode 100644
index 00000000000..3b20e162326
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa27560def7048d7b4a095.md
@@ -0,0 +1,368 @@
+---
+id: 62aa27560def7048d7b4a095
+title: Step 165
+challengeType: 0
+dashedName: step-165
+---
+
+# --description--
+
+Before the final quote in that string you added, insert the new line escape character `\n`. This will cause the next part you add to `text.innerText` to appear on a new line.
+
+# --hints--
+
+You should add the new line escape character `\n` to your `. Here are the random numbers: ` string.
+
+```js
+assert.match(pick.toString(), /text\.innerText\s*=\s*('|")You picked \1\s*\+\s*guess\s*\+\s*('|")\.\sHere are the random numbers:\\n\2/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:";
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa27c40ca6f04ab8be5fac.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa27c40ca6f04ab8be5fac.md
new file mode 100644
index 00000000000..180270940d6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa27c40ca6f04ab8be5fac.md
@@ -0,0 +1,375 @@
+---
+id: 62aa27c40ca6f04ab8be5fac
+title: Step 166
+challengeType: 0
+dashedName: step-166
+---
+
+# --description--
+
+A `for` loop runs for a specific number of times. We will break down how a `for` loop runs in the next several steps. For now, copy this loop below and paste it at the end of your `pick` function.
+
+```js
+for (let x = 1; x < 5; x++) {
+
+}
+```
+
+# --hints--
+
+You should copy the above loop into your `pick` function.
+
+```js
+assert.match(pick.toString(), /for\s*\(\s*(let|var)\s*x\s*=\s*1\s*;\s*x\s*<\s*5\s*;\s*x\s*\+\+\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:\n";
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa28032d863d4bd8058799.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa28032d863d4bd8058799.md
new file mode 100644
index 00000000000..4b4af2f8669
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa28032d863d4bd8058799.md
@@ -0,0 +1,375 @@
+---
+id: 62aa28032d863d4bd8058799
+title: Step 167
+challengeType: 0
+dashedName: step-167
+---
+
+# --description--
+
+`for` loops are declared with three expressions separated by semicolons. `for (a; b; c)`, where `a` is the initialization expression, `b` is the condition, and `c` is the final expression.
+
+The initialization expression is executed only once, before the loop starts, and is often used to define and set up the loop variable. Think of it like declaring a counter to use in your loop.
+
+Many `for` loops use `i` as the counter and start from 0, so change `let x = 1;` to `let i = 0;`.
+
+# --hints--
+
+You should change your initialization in the `for` loop to be `let i = 0;`.
+
+```js
+assert.match(pick.toString(), /for\s*\(\s*(let|var)\s*i\s*=\s*0\s*;/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:\n";
+ for (let x = 1; x < 5; x++) {
+
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa287434dc284cea01157c.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa287434dc284cea01157c.md
new file mode 100644
index 00000000000..7067e31d3f3
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa287434dc284cea01157c.md
@@ -0,0 +1,373 @@
+---
+id: 62aa287434dc284cea01157c
+title: Step 168
+challengeType: 0
+dashedName: step-168
+---
+
+# --description--
+
+The second statement in a `for` loop, the condition statement, is evaluated at the beginning of every loop iteration. The loop will continue as long as the condition evaluates to be true.
+
+We want the loop to run 10 times, so change `x < 5` to `i < 10`.
+
+# --hints--
+
+You should update your condition statement to be `i < 10`.
+
+```js
+assert.match(pick.toString(), /for\s*\(\s*(let|var)\s*i\s*=\s*0\s*;\s*i\s*<\s*10\s*;/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:\n";
+ for (let i = 0; x < 5; x++) {
+
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa28bbd6323e4dfb3ac43e.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa28bbd6323e4dfb3ac43e.md
new file mode 100644
index 00000000000..72bbc1f15f8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa28bbd6323e4dfb3ac43e.md
@@ -0,0 +1,373 @@
+---
+id: 62aa28bbd6323e4dfb3ac43e
+title: Step 169
+challengeType: 0
+dashedName: step-169
+---
+
+# --description--
+
+The last statement in a `for` loop, the final expression, is executed at the end of each loop iteration.
+
+Since we changed the initialization statement to use `i` instead of `x`, change `x++` to `i++`. This will increment the initializer `i` by 1 after each loop.
+
+# --hints--
+
+You should change your final expression to `i++`.
+
+```js
+assert.match(pick.toString(), /for\s*\(\s*(let|var)\s*i\s*=\s*0\s*;\s*i\s*<\s*10\s*;\s*i\+\+\s*\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:\n";
+ for (let i = 0; i < 10; x++) {
+
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa28fb651bf14efa2dbb16.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa28fb651bf14efa2dbb16.md
new file mode 100644
index 00000000000..94da3ef415e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa28fb651bf14efa2dbb16.md
@@ -0,0 +1,390 @@
+---
+id: 62aa28fb651bf14efa2dbb16
+title: Step 170
+challengeType: 0
+dashedName: step-170
+---
+
+# --description--
+
+Now you can write the logic to run in the loop. Inside your `for` loop, use the `+=` operator to add to the end of `text.innerText`. Add the number at index `i` of the `numbers` array, using `numbers[i]`. Then add a new line, using the escape sequence you used earlier.
+
+# --hints--
+
+You should use compound assignment to add to the end of `text.innerText`.
+
+```js
+assert.match(pick.toString(), /text\.innerText\s*\+=/);
+```
+
+You should use bracket notation to access `numbers[i]`.
+
+```js
+assert.match(pick.toString(), /numbers\[i\]/);
+```
+
+You should add `numbers[i]` to your `text.innerText` value.
+
+```js
+assert.match(pick.toString(), /text\.innerText\s*\+=\s*numbers\[i\]/);
+```
+
+You should add a new-line character after the `numbers[i]` value. Remember that you can do this with `\n`.
+
+```js
+console.log(pick.toString());
+assert.match(pick.toString(), /text\.innerText\s*\+=\s*numbers\[i\]\s*\+\s*('|")\\n\1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:\n";
+ for (let i = 0; i < 10; i++) {
+
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2943669c9d5026af6985.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2943669c9d5026af6985.md
new file mode 100644
index 00000000000..b1540f1ac41
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2943669c9d5026af6985.md
@@ -0,0 +1,387 @@
+---
+id: 62aa2943669c9d5026af6985
+title: Step 171
+challengeType: 0
+dashedName: step-171
+---
+
+# --description--
+
+The `indexOf()` array method returns the first index at which a given element can be found in the array, or `-1` if the element is not present.
+
+After your `for` loop, add an `if` expression to check if the `guess` is in the `numbers` array. You can check if `indexOf` is not equal (`!==`) to `-1`.
+
+Here is an example of the `indexOf` syntax:
+
+```js
+const numbers = [1, 2, 3];
+numbers.indexOf(2) // 1
+```
+
+# --hints--
+
+Your `pick` function should have an `if` statement.
+
+```js
+assert.match(pick.toString(), /if/);
+```
+
+Your `if` statement should check if the `guess` is in the `numbers` array. You can check if `indexOf` is not equal (`!==`) to `-1`.
+
+```js
+assert.match(pick.toString(), /if\s*\(numbers\.indexOf\(\s*guess\s*\)\s*!==\s*-1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:\n";
+ for (let i = 0; i < 10; i++) {
+ text.innerText += numbers[i] + "\n";
+ }
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2999ec27ec516655eba6.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2999ec27ec516655eba6.md
new file mode 100644
index 00000000000..aa044de71f3
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2999ec27ec516655eba6.md
@@ -0,0 +1,386 @@
+---
+id: 62aa2999ec27ec516655eba6
+title: Step 172
+challengeType: 0
+dashedName: step-172
+---
+
+# --description--
+
+Inside the `if` expression, add the string `Right! You win 20 gold!` to the end of `text.innerText`. Also, add `20` to the value of `gold` and update the `goldText.innerText`.
+
+# --hints--
+
+You should use compound assignment to add the string `Right! You win 20 gold!` to the end of `text.innerText`.
+
+```js
+assert.match(pick.toString(), /text\.innerText\s*\+=\s*('|")Right! You win 20 gold!\1/);
+```
+
+You should use compound assignment add `20` to the value of `gold`.
+
+```js
+assert.match(pick.toString(), /gold\s*\+=\s*20/);
+```
+
+You should update the `goldText.innerText` to reflect the new value of `gold`.
+
+```js
+assert.match(pick.toString(), /goldText\.innerText\s*\=\s*gold/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:\n";
+ for (let i = 0; i < 10; i++) {
+ text.innerText += numbers[i] + "\n";
+ }
+ if (numbers.indexOf(guess) !== -1) {
+
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa29d8f8f88152c91350ca.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa29d8f8f88152c91350ca.md
new file mode 100644
index 00000000000..13ed8152080
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa29d8f8f88152c91350ca.md
@@ -0,0 +1,394 @@
+---
+id: 62aa29d8f8f88152c91350ca
+title: Step 173
+challengeType: 0
+dashedName: step-173
+---
+
+# --description--
+
+Now add an `else` expression. Inside, add `Wrong! You lose 10 health!` to the end of `text.innerText`. Subtract `10` from `health` and update `healthText.innerText`.
+
+# --hints--
+
+You should add an `else` block.
+
+```js
+assert.match(pick.toString(), /else\s*\{/);
+```
+
+Your `else` block should use compound assignment to add `Wrong! You lose 10 health!` to the end of `text.innerText`.
+
+```js
+assert.match(pick.toString(), /text\.innerText\s*\+=\s*('|")Wrong! You lose 10 health!\1/);
+```
+
+Your `else` block should use compound assignment to subtract `10` from `health`.
+
+```js
+assert.match(pick.toString(), /health\s*-=\s*10/);
+```
+
+Your `else` block should update the `healthText.innerText` to reflect the new value of `health`.
+
+```js
+assert.match(pick.toString(), /healthText\.innerText\s*=\s*health/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:\n";
+ for (let i = 0; i < 10; i++) {
+ text.innerText += numbers[i] + "\n";
+ }
+ if (numbers.indexOf(guess) !== -1) {
+ text.innerText += "Right! You win 20 gold!";
+ gold += 20;
+ goldText.innerText = gold;
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2aec2f09d454253aad6c.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2aec2f09d454253aad6c.md
new file mode 100644
index 00000000000..5f48991b690
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2aec2f09d454253aad6c.md
@@ -0,0 +1,394 @@
+---
+id: 62aa2aec2f09d454253aad6c
+title: Step 174
+challengeType: 0
+dashedName: step-174
+---
+
+# --description--
+
+Since you subtracted health from the player, you need to check `if` the player's `health` is less than or equal to `0`. If it is, call the `lose` function.
+
+# --hints--
+
+Your `pick` function should have a second `if` statement.
+
+```js
+const match = pick.toString().match(/if/g);
+assert.isAtLeast(match.length, 2);
+```
+
+Your `if` statement should check if the player's `health` is less than or equal to `0`.
+
+```js
+assert.match(pick.toString(), /if\s*\(\s*health\s*<=\s*0\s*\)/);
+```
+
+Your `if` statement should call the `lose` function.
+
+```js
+assert.match(pick.toString(), /lose\(\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+--fcc-editable-region--
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:\n";
+ for (let i = 0; i < 10; i++) {
+ text.innerText += numbers[i] + "\n";
+ }
+ if (numbers.indexOf(guess) !== -1) {
+ text.innerText += "Right! You win 20 gold!";
+ gold += 20;
+ goldText.innerText = gold;
+ } else {
+ text.innerText += "Wrong! You lose 10 health!";
+ health -= 10;
+ healthText.innerText = health;
+
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2ba9cd881355a6f0a5a8.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2ba9cd881355a6f0a5a8.md
new file mode 100644
index 00000000000..f9bcbbb6387
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa2ba9cd881355a6f0a5a8.md
@@ -0,0 +1,746 @@
+---
+id: 62aa2ba9cd881355a6f0a5a8
+title: Step 175
+challengeType: 0
+dashedName: step-175
+---
+
+# --description--
+
+Looking at your `kill monster` object, `button functions` currently has three `goTown` variables. Replace the third one with `easterEgg` - this is how a player will access the hidden feature of the game. Do not change the `button text`.
+
+With this, your RPG game is complete! You can now play around - can you defeat the dragon?
+
+# --hints--
+
+You should update your fifth `locations` object to have a `button functions` property of `[goTown, goTown, easterEgg]`.
+
+```js
+assert.deepEqual(locations[4]["button functions"], [goTown, goTown, easterEgg]);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+--fcc-editable-region--
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+--fcc-editable-region--
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:\n";
+ for (let i = 0; i < 10; i++) {
+ text.innerText += numbers[i] + "\n";
+ }
+ if (numbers.indexOf(guess) !== -1) {
+ text.innerText += "Right! You win 20 gold!";
+ gold += 20;
+ goldText.innerText = gold;
+ } else {
+ text.innerText += "Wrong! You lose 10 health!";
+ health -= 10;
+ healthText.innerText = health;
+ if (health <= 0) {
+ lose();
+ }
+ }
+}
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, easterEgg],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+ {
+ name: "lose",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You die. ☠️"
+ },
+ {
+ name: "win",
+ "button text": ["REPLAY?", "REPLAY?", "REPLAY?"],
+ "button functions": [restart, restart, restart],
+ text: "You defeat the dragon! YOU WIN THE GAME! 🎉"
+ },
+ {
+ name: "easter egg",
+ "button text": ["2", "8", "Go to town square?"],
+ "button functions": [pickTwo, pickEight, goTown],
+ text: "You find a secret game. Pick a number above. Ten numbers will be randomly chosen between 0 and 10. If the number you choose matches one of the random numbers, you win!"
+ }
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= getMonsterAttackValue(monsters[fighting].level);
+ if (isMonsterHit()) {
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ } else {
+ text.innerText += " You miss.";
+ }
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ fighting === 2 ? winGame() : defeatMonster();
+ }
+ if (Math.random() <= .1 && inventory.length !== 1) {
+ text.innerText += " Your " + inventory.pop() + " breaks.";
+ currentWeapon--;
+ }
+}
+
+function getMonsterAttackValue(level) {
+ const hit = (level * 5) - (Math.floor(Math.random() * xp));
+ console.log(hit);
+ return hit > 0 ? hit : 0;
+}
+
+function isMonsterHit() {
+ return Math.random() > .2 || health < 20;
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function winGame() {
+ update(locations[6]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+
+function easterEgg() {
+ update(locations[7]);
+}
+
+function pickTwo() {
+ pick(2);
+}
+
+function pickEight() {
+ pick(8);
+}
+
+function pick(guess) {
+ let numbers = [];
+ while (numbers.length < 10) {
+ numbers.push(Math.floor(Math.random() * 11));
+ }
+ text.innerText = "You picked " + guess + ". Here are the random numbers:\n";
+ for (let i = 0; i < 10; i++) {
+ text.innerText += numbers[i] + "\n";
+ }
+ if (numbers.indexOf(guess) !== -1) {
+ text.innerText += "Right! You win 20 gold!";
+ gold += 20;
+ goldText.innerText = gold;
+ } else {
+ text.innerText += "Wrong! You lose 10 health!";
+ health -= 10;
+ healthText.innerText = health;
+ if (health <= 0) {
+ lose();
+ }
+ }
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62b46e3a8d4be31be5af793d.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62b46e3a8d4be31be5af793d.md
new file mode 100644
index 00000000000..d98f9e81298
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62b46e3a8d4be31be5af793d.md
@@ -0,0 +1,121 @@
+---
+id: 62b46e3a8d4be31be5af793d
+title: Step 30
+challengeType: 0
+dashedName: step-30
+---
+
+# --description--
+
+We have run in to a slight problem. You are trying to query your page for a button element, but your `script` tag is in the `head` of your HTML. This means your code runs before the browser has finished reading the HTML, and your `document.querySelector()` will not see the button - because the browser hasn't processed it yet.
+
+To fix this, move your `script` element out of the `head` element, and place it at the end of your `body` element (just before the closing `` tag.)
+
+# --hints--
+
+Your `script` element should not be in your `head` element.
+
+```js
+const script = document.querySelector('script[data-src$="script.js"]');
+assert.notEqual(script.parentElement.tagName, "HEAD");
+```
+
+Your `script` element should come at the end of your `body` element.
+
+```js
+const script = document.querySelector('script[data-src$="script.js"]');
+assert.equal(script.previousElementSibling.tagName, "DIV");
+assert.isNull(script.nextElementSibling);
+assert.equal(script.parentElement.tagName, "BODY");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+--fcc-editable-region--
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+--fcc-editable-region--
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+let button1 = document.querySelector("#button1");
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62ba17beef16c563069a65d8.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62ba17beef16c563069a65d8.md
new file mode 100644
index 00000000000..e5d8098b79a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62ba17beef16c563069a65d8.md
@@ -0,0 +1,339 @@
+---
+id: 62ba17beef16c563069a65d8
+title: Step 137
+challengeType: 0
+dashedName: step-137
+---
+
+# --description--
+
+In the `locations` array, add another object at the end. Set the `name` property to `lose`, set `button text` to an array with three `REPLAY?` strings, set `button functions` to an array with three `restart` variables, and set `text` to `You die. ☠️`. You can copy that text to use the emote.
+
+# --hints--
+
+You should have six values in the `locations` array.
+
+```js
+assert.lengthOf(locations, 6);
+```
+
+Your sixth `locations` value should be an object.
+
+```js
+assert.isObject(locations[5]);
+```
+
+Your sixth `locations` value should have a `name` property with the value `lose`.
+
+```js
+assert.equal(locations[5].name, 'lose');
+```
+
+Your sixth `locations` value should have a `button text` property with the value an array with three `REPLAY?` strings.
+
+```js
+assert.deepEqual(locations[5]["button text"], ['REPLAY?', 'REPLAY?', 'REPLAY?']);
+```
+
+Your sixth `locations` value should have a `button functions` property with the value an array with three `restart` variables.
+
+```js
+assert.deepEqual(locations[5]["button functions"], [restart, restart, restart]);
+```
+
+Your sixth `locations` value should have a `text` property with the value `You die. ☠️`.
+
+```js
+assert.equal(locations[5].text, 'You die. ☠️');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+const button1 = document.querySelector('#button1');
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+const monsterHealthText =document.querySelector("#monsterHealth");
+const weapons = [
+ { name: 'stick', power: 5 },
+ { name: 'dagger', power: 30 },
+ { name: 'claw hammer', power: 50 },
+ { name: 'sword', power: 100 }
+];
+const monsters = [
+ {
+ name: "slime",
+ level: 2,
+ health: 15
+ },
+ {
+ name: "fanged beast",
+ level: 8,
+ health: 60
+ },
+ {
+ name: "dragon",
+ level: 20,
+ health: 300
+ }
+]
+const locations = [
+ {
+ name: "town square",
+ "button text": ["Go to store", "Go to cave", "Fight dragon"],
+ "button functions": [goStore, goCave, fightDragon],
+ text: "You are in the town square. You see a sign that says \"Store\"."
+ },
+ {
+ name: "store",
+ "button text": ["Buy 10 health (10 gold)", "Buy weapon (30 gold)", "Go to town square"],
+ "button functions": [buyHealth, buyWeapon, goTown],
+ text: "You enter the store."
+ },
+ {
+ name: "cave",
+ "button text": ["Fight slime", "Fight fanged beast", "Go to town square"],
+ "button functions": [fightSlime, fightBeast, goTown],
+ text: "You enter the cave. You see some monsters."
+ },
+ {
+ name: "fight",
+ "button text": ["Attack", "Dodge", "Run"],
+ "button functions": [attack, dodge, goTown],
+ text: "You are fighting a monster."
+ },
+ {
+ name: "kill monster",
+ "button text": ["Go to town square", "Go to town square", "Go to town square"],
+ "button functions": [goTown, goTown, goTown],
+ text: 'The monster screams "Arg!" as it dies. You gain experience points and find gold.'
+ },
+--fcc-editable-region--
+
+--fcc-editable-region--
+];
+
+// initialize buttons
+button1.onclick = goStore;
+button2.onclick = goCave;
+button3.onclick = fightDragon;
+
+function update(location) {
+ monsterStats.style.display = "none";
+ button1.innerText = location["button text"][0];
+ button2.innerText = location["button text"][1];
+ button3.innerText = location["button text"][2];
+ button1.onclick = location["button functions"][0];
+ button2.onclick = location["button functions"][1];
+ button3.onclick = location["button functions"][2];
+ text.innerText = location.text;
+}
+
+function goTown() {
+ update(locations[0]);
+}
+
+function goStore() {
+ update(locations[1]);
+}
+
+function goCave() {
+ update(locations[2]);
+}
+
+function buyHealth() {
+ if (gold >= 10) {
+ gold -= 10;
+ health += 10;
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ } else {
+ text.innerText = "You do not have enough gold to buy health.";
+ }
+}
+
+function buyWeapon() {
+ if (currentWeapon < weapons.length - 1) {
+ if (gold >= 30) {
+ gold -= 30;
+ currentWeapon++;
+ goldText.innerText = gold;
+ let newWeapon = weapons[currentWeapon].name;
+ text.innerText = "You now have a " + newWeapon + ".";
+ inventory.push(newWeapon);
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "You do not have enough gold to buy a weapon.";
+ }
+ } else {
+ text.innerText = "You already have the most powerful weapon!";
+ button2.innerText = "Sell weapon for 15 gold";
+ button2.onclick = sellWeapon;
+ }
+}
+
+function sellWeapon() {
+ if (inventory.length > 1) {
+ gold += 15;
+ goldText.innerText = gold;
+ let currentWeapon = inventory.shift();
+ text.innerText = "You sold a " + currentWeapon + ".";
+ text.innerText += " In your inventory you have: " + inventory;
+ } else {
+ text.innerText = "Don't sell your only weapon!";
+ }
+}
+
+function fightSlime() {
+ fighting = 0;
+ goFight();
+}
+
+function fightBeast() {
+ fighting = 1;
+ goFight();
+}
+
+function fightDragon() {
+ fighting = 2;
+ goFight();
+}
+
+function goFight() {
+ update(locations[3]);
+ monsterHealth = monsters[fighting].health;
+ monsterStats.style.display = "block";
+ monsterName.innerText = monsters[fighting].name;
+ monsterHealthText.innerText = monsterHealth;
+}
+
+function attack() {
+ text.innerText = "The " + monsters[fighting].name + " attacks.";
+ text.innerText += " You attack it with your " + weapons[currentWeapon].name + ".";
+ health -= monsters[fighting].level;
+ monsterHealth -= weapons[currentWeapon].power + Math.floor(Math.random() * xp) + 1;
+ healthText.innerText = health;
+ monsterHealthText.innerText = monsterHealth;
+ if (health <= 0) {
+ lose();
+ } else if (monsterHealth <= 0) {
+ defeatMonster();
+ }
+}
+
+function dodge() {
+ text.innerText = "You dodge the attack from the " + monsters[fighting].name;
+}
+
+function defeatMonster() {
+ gold += Math.floor(monsters[fighting].level * 6.7);
+ xp += monsters[fighting].level;
+ goldText.innerText = gold;
+ xpText.innerText = xp;
+ update(locations[4]);
+}
+
+function lose() {
+ update(locations[5]);
+}
+
+function restart() {
+ xp = 0;
+ health = 100;
+ gold = 50;
+ currentWeapon = 0;
+ inventory = ["stick"];
+ goldText.innerText = gold;
+ healthText.innerText = health;
+ xpText.innerText = xp;
+ goTown();
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62fc1ee0c5a89717d4785729.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62fc1ee0c5a89717d4785729.md
new file mode 100644
index 00000000000..50b06ed7911
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62fc1ee0c5a89717d4785729.md
@@ -0,0 +1,114 @@
+---
+id: 62fc1ee0c5a89717d4785729
+title: Step 12
+challengeType: 0
+dashedName: step-12
+---
+
+# --description--
+
+Give your `#monsterStats` element the same `border` and `padding` as your `#stats` element. Set its color to `white` and give it a `red` background.
+
+# --hints--
+
+You should have a `#monsterStats` selector.
+
+```js
+const monsterStats = new __helpers.CSSHelp(document).getStyle('#monsterStats');
+assert.exists(monsterStats);
+```
+
+Your `#monsterStats` selector should have a `border` of `1px solid black`.
+
+```js
+const border = new __helpers.CSSHelp(document).getStyle('#monsterStats')?.getPropertyValue('border');
+assert.equal(border, '1px solid black');
+```
+
+Your `#monsterStats` selector should have `5px` of padding.
+
+```js
+const padding = new __helpers.CSSHelp(document).getStyle('#monsterStats')?.getPropertyValue('padding');
+assert.equal(padding, '5px');
+```
+
+Your `#monsterStats` selector should have a `color` of `white`.
+
+```js
+const color = new __helpers.CSSHelp(document).getStyle('#monsterStats')?.getPropertyValue('color');
+assert.equal(color, 'white');
+```
+
+Your `#monsterStats` selector should have a `background-color` of `red`.
+
+```js
+const background = new __helpers.CSSHelp(document).getStyle('#monsterStats')?.getPropertyValue('background-color');
+assert.equal(background, 'red');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62fc20387ef88d1d1998aac5.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62fc20387ef88d1d1998aac5.md
new file mode 100644
index 00000000000..1b122cb50c8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62fc20387ef88d1d1998aac5.md
@@ -0,0 +1,127 @@
+---
+id: 62fc20387ef88d1d1998aac5
+title: Step 32
+challengeType: 0
+dashedName: step-32
+---
+
+# --description--
+
+Use `querySelector()` to get the other two button elements, using their `#button2` and `#button3` `id`s. Store them in variables called `button2` and `button3`. Remember to use `const`.
+
+# --hints--
+
+You should declare a `button2` variable with `const`.
+
+```js
+assert.match(code, /const button2/);
+```
+
+Your `button2` variable should have the value of your `#button2` element.
+
+```js
+assert.deepEqual(button2, document.querySelector('#button2'));
+```
+
+You should declare a `button3` variable with `const`.
+
+```js
+assert.match(code, /const button3/);
+```
+
+Your `button3` variable should have the value of your `#button3` element.
+
+```js
+assert.deepEqual(button3, document.querySelector('#button3'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+--fcc-editable-region--
+const button1 = document.querySelector("#button1");
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62fc211760bfc220f4734800.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62fc211760bfc220f4734800.md
new file mode 100644
index 00000000000..5dd815b61c0
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62fc211760bfc220f4734800.md
@@ -0,0 +1,123 @@
+---
+id: 62fc211760bfc220f4734800
+title: Step 34
+challengeType: 0
+dashedName: step-34
+---
+
+# --description--
+
+Finally, use `querySelector()` to get the `#monsterHealth` element. Because you have already declared a `monsterHealth` variable earlier, you need to use a different variable name for this element. Declare a new variable with the `const` keyword and name it `monsterHealthText`.
+
+# --hints--
+
+You should declare a `monsterHealthText` variable with `const`.
+
+```js
+assert.match(code, /const monsterHealthText/);
+```
+
+Your `monsterHealthText` variable should have the value of your `#monsterHealth` element.
+
+```js
+assert.deepEqual(monsterHealthText, document.querySelector('#monsterHealth'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+ RPG - Dragon Repeller
+
+
+
+
+ XP: 0
+ Health: 100
+ Gold: 50
+
+
+
+
+
+
+
+ Monster Name:
+ Health:
+
+
+ Welcome to Dragon Repeller. You must defeat the dragon that is preventing people from leaving the town. You are in the town square. Where do you want to go? Use the buttons above.
+
+
+
+
+
+```
+
+```css
+body {
+ background-color: darkblue;
+}
+
+#text {
+ background-color: black;
+ color: white;
+ padding: 10px;
+}
+
+#game {
+ max-width: 500px;
+ max-height: 400px;
+ background-color: lightgray;
+ color: white;
+ margin: 0 auto;
+ padding: 10px;
+}
+
+#controls, #stats {
+ border: 1px solid black;
+ padding: 5px;
+ color: black;
+}
+
+#monsterStats {
+ display: none;
+ border: 1px solid black;
+ padding: 5px;
+ color: white;
+ background-color: red;
+}
+
+.stat {
+ padding-right: 10px;
+}
+```
+
+```js
+let xp = 0;
+let health = 100;
+let gold = 50;
+let currentWeapon = 0;
+let fighting;
+let monsterHealth;
+let inventory = ["stick"];
+
+--fcc-editable-region--
+const button1 = document.querySelector("#button1");
+const button2 = document.querySelector("#button2");
+const button3 = document.querySelector("#button3");
+const text = document.querySelector("#text");
+const xpText = document.querySelector("#xpText");
+const healthText = document.querySelector("#healthText");
+const goldText = document.querySelector("#goldText");
+const monsterStats = document.querySelector("#monsterStats");
+const monsterName = document.querySelector("#monsterName");
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-001.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-001.md
new file mode 100644
index 00000000000..a2ce162457c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-001.md
@@ -0,0 +1,100 @@
+---
+id: 5ddb965c65d27e1512d44d9a
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+When a browser loads a page, it creates a Document Object Model (DOM) representation of the page which includes all of the HTML elements in a tree structure.
+
+In JavaScript, you can access the DOM by referencing the global `document` object.
+
+To view the DOM, log it to the console with `console.log(document)`.
+
+# --hints--
+
+See description above for instructions.
+
+```js
+assert(code.replace(/\s/g, '').match(/console\.log\(document\)/));
+```
+
+# --seed--
+
+## --before-user-code--
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## --after-user-code--
+
+```html
+
+
+```
+
+## --seed-contents--
+
+```html
+
+```
+
+# --solutions--
+
+```html
+
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-002.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-002.md
new file mode 100644
index 00000000000..aab244748d6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-002.md
@@ -0,0 +1,114 @@
+---
+id: 5ddb965c65d27e1512d44d9b
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+In our HTML document, we have a form element with an `id` attribute: `