Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              <div class="wrapper">
    <div id="app">
    </div>
 </div>
            
          
!
            
              * {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  background-color: #000000;
  font-family: 'Roboto Mono', monospace;
}
.wrapper {
  margin: 0 auto;
  width:820px;
}
.screen {
  border: 6px double #AAAAAA;
  height: 605px;
}
.left-column {
  float: left;
  width: 300px;
  padding: 0 5px;
  margin: 10px 0 0 10px;
}
.logo-area {
  color: #0A0;
  text-align: center;
}
.small-signature {
  font-size: 12px;
}
.hero-box {
  color:#55F;
  margin: 10px 0;
}

.menu {
  margin: 10px 0;
}

.btn {
  background-color: #AAA;
    border: 5px outset #888;
    border-radius: 5px;
    color: #000;
    padding: 5px 5px;
    margin-right: 10px;
    text-align: center;
    display: inline-block;
    font-size: 16px;
    coursor: pointer;
    outline:0;
    font-family: 'Roboto Mono', monospace;
}
.btn:hover {
  border: 5px inset #888;
  cursor: pointer;
}
.list {
  list-style-type: none;
}
.key {
  color:#ccc;
  font-family: 'Roboto Mono', monospace;
  text-align: left;
  font-size: 14px;
}
.chars {
  font-family: 'Space Mono', monospace;
}

.map {
  margin: 10px 10px 0 0;
  float: right;
  font-size: 28px;
  line-height: 28px;
  width: 487px;
  height: 483px;
  letter-spacing: 4px;
  border: 2px solid #aaa;
  /* overflow: hidden */
}

.map pre {
  font-family: 'Space Mono', monospace;
  background-color: #000;
  color: #aaa;
}

.message-box {
  clear:both;
  height: 80;
  margin: 10px;
  padding:5px 10px;
  background-color: #000;
  color: #dd3;
  font-size: 16px;
  font-family: 'Roboto Mono', monospace;
}

            
          
!
            
              const app = document.getElementById('app');

let weapons = [
  { level: 1, name: "shiv", strength: 5,  x: 0, y: 0},
  { level: 1, name: "knife", strength: 7, x:0, y:0},
  { level: 2, name: "dagger", strength: 10, x:0, y:0},
  { level: 2, name: "short sword", strength:12, x:0, y:0},
  { level: 3, name: "sword", strength: 15, x:0, y:0},
  { level: 3, name: "long sword", strength: 18, x:0, y:0},
  { level: 4, name: "magic sword", strength: 20, x:0, y:0}
];

let monsters = [
  { level: 1, name: "spider", attack: 6, health:20},
  { level: 2, name: "rat", attack: 8, health:23},
  { level: 3, name: "dwarf", attack: 10, health:26},
  { level: 4, name: "Boss", attack: 20, health:80}
];

const level1 = [ "################################",
                "################################",
                "##                            ##",
                "##  /   #   #      #   #      ##",
                "##      #   #      #   #      ##",
                "#########   ########   #########",
                "##                            ##",
                "##     ##    ######    ##     ##",
                "##     ##    ######    ##     ##",
                "##                            ##",
                "##                            ##",
                "##     ##              ##     ##",
                "##     ##              ##     ##",
                "##                            ##",
                "##                            ##",
                "##     ##              ##     ##",
                "##     ##              ##     ##",
                "##                            ##",
                "##                            ##",
                "##     ##              ##     ##",
                "##     ##              ##     ##",
                "##                            ##",
                "##                            ##",
                "##     ##              ##     ##",
                "##     ##              ##     ##",
                "##                            ##",
                "##                            ##",
                "##     ##              ##     ##",
                "##     ##              ##     ##",
                "##                            ##",
                "##                            ##",
                "##     ##              ##     ##",
                "##     ##              ##     ##",
                "##                            ##",
                "##                            ##",
                "####    ####        ####    ####",
                "####    ####        ####    ####",
                "##                            ##",
                "##                            ##",
                "##                            ##",
                "################################",
                "################################",
];

const level2 = [  "################################",
                "################################",
                "##                #           ##",
                "##                            ##",
                "##                #           ##",
                "##############    ##############",
                "##           #    #           ##",
                "##           #    #           ##",
                "##                            ##",
                "##           #    #           ##",
                "##           #    #           ##",
                "##           #    #           ##",
                "##############    ##############",
                "##           #    #           ##",
                "##           #    #           ##",
                "##                            ##",
                "##           #    #           ##",
                "##           #    #           ##",
                "##           #    #           ##",
                "######   #####    ##############",
                "##           #    #           ##",
                "##           #    #           ##",
                "##           #                ##",
                "##           #    #           ##",
                "##           #    #           ##",
                "##           #    #           ##",
                "##############    ##############",
                "##           #    #           ##",
                "##                            ##",
                "##           #    #           ##",
                "##           #    #           ##",
                "##############    #           ##",
                "##           #    #           ##",
                "##                #           ##",
                "##           #    #           ##",
                "##           #    #           ##",
                "##############    ##############",
                "##                            ##",
                "##                         /  ##",
                "##                            ##",
                "################################",
                "################################",
];

const level3 = [  "################################",
                "################################",
                "###    #########################",
                "##   /  ########################",
                "##     #########################",
                "##    ##########################",
                "###   ############     #########",
                "###   #########        #########",
                "###    #######          ########",
                "####    #######       ##########",
                "####     ######       ##########",
                "#####     ###      #############",
                "######           ###############",
                "#######      ###################",
                "########       #################",
                "##########       ###############",
                "############        ############",
                "###############        #########",
                "#################        #######",
                "#################       ########",
                "#################      #########",
                "################      ##########",
                "#################    ###########",
                "################      ##########",
                "##############          ########",
                "###########              #######",
                "############     #####    ######",
                "##########     #####        ####",
                "########     ##########     ####",
                "#######     ###########       ##",
                "########    ############     ###",
                "#######       ###########    ###",
                "#########        #####      ####",
                "########                  ######",
                "###############             ####",
                "##################           ###",
                "######################    ######",
                "######################    ######",
                "##################            ##",
                "##################            ##",
                "##################            ##",
                "##################            ##",
                "################################",
                "################################",
];

const level4 =[   "################################",
                "################################",
                "###    #########################",
                "##      ########################",
                "##     #########################",
                "##    ##########################",
                "###     ########################",
                "###    #########################",
                "###     ########################",
                "####      ######################",
                "####     #######################",
                "#####     ######################",
                "######           ###############",
                "#######       ##################",
                "########       #################",
                "####                        ####",
                "####                        ####",
                "####                        ####",
                "####                        ####",
                "####    ####        ####    ####",
                "####    ####        ####    ####",
                "####    ####        ####    ####",
                "####    ####        ####    ####",
                "####                        ####",
                "####                        ####",
                "####                        ####",
                "####                        ####",
                "####    ####        ####    ####",
                "####    ####        ####    ####",
                "####    ####        ####    ####",
                "####    ####        ####    ####",
                "####                        ####",
                "####                        ####",
                "####                        ####",
                "####                        ####",
                "################################",
                "################################",
                "################################",
                "################################",
                "################################",
                "################################",
                "################################"
];

let monstersOnMap=[], monsterID=0;
let testMap = level1.slice();

class Monster {
  constructor(monster) {
    this.id = monster.id;
    this.x = monster.x;
    this.y = monster.y;
    this.name = monster.name;
    this.attack = monster.attack;
    this.health = monster.health;
    this.level = monster.level;
    monsterID++;
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
      this.state = {
        map: testMap,
        level: 1,
        heroY: 38,
        heroX: 9,
        heroHealth: 100,
        heroLevel: 1,
        heroWeapon: "fist",
        heroWeaponStrength: 3,
        heroExperience: 0,
        heroNextLevel: 25,
        heroSeesAll: false,
        message: "Click anywhere and use arrows to move.",
        endGame: false
      };
    this.addItemsToMap = this.addItemsToMap.bind(this);
    this.handleKeyEvent = this.handleKeyEvent.bind(this);
    this.checkField = this.checkField.bind(this);
    this.move = this.move.bind(this);
    this.toggleDarkness = this.toggleDarkness.bind(this);
    this.loadMap = this.loadMap.bind(this);
    this.reset = this.reset.bind(this);
    
  }

  addItemsToMap(level) {
    //add hero to map
    let beforeHero = this.state.map[this.state.heroY].substr(0,this.state.heroX);
    let afterHero = this.state.map[this.state.heroY].substr(this.state.heroX+1);
    let heroRow = beforeHero+"H"+afterHero;
    testMap[this.state.heroY] = heroRow;
    // add one item to map
    let mapLengthY = this.state.map.length;
    let lastLevel = this.state.level; // level 4

    function addItemToMap(item,howMany) {
      while (howMany>0) {
        let rowY = Math.floor(Math.random()*mapLengthY);
        let rowLength = testMap[rowY].length;
        let rowX = Math.floor(Math.random()*rowLength);
        let field = testMap[rowY][rowX];
        if (field===" ") {
          // add weapons section
          if (item!=="+" && item!=="m") {
            for (let i=0; i<weapons.length; i++){
              if (weapons[i].name===item) {
                weapons[i].x = rowX;
                weapons[i].y = rowY;
              }
            }
            item="w";
          }
          // add monster section
          if (item==="m") {
            let tableIndex = level -1;
            let newMonsterToAdd = {
              id: monsterID,
              x: rowX,
              y: rowY,
              name: monsters[tableIndex].name,
              attack: monsters[tableIndex].attack,
              health: monsters[tableIndex].health,
              level: monsters[tableIndex].level
            }
            let newMonster = new Monster(newMonsterToAdd);
            monstersOnMap.push(newMonster);
            if (lastLevel===4) item="B";  //add boss char on the last level
          }
          // change/draw map row after randomly added item
          let beforeField = testMap[rowY].substr(0,rowX);
          let afterField = testMap[rowY].substr(rowX+1);
          let itemToAdd = item;
          let addItemToRow = beforeField+itemToAdd+afterField;
          testMap[rowY] = addItemToRow;
          howMany--;
        }
      }
    }
    /* Game stuff to add to level*/
    // add weapons from table
    for (let i=0; i < weapons.length; i++) {
      if (weapons[i].level===level) {
        addItemToMap(weapons[i].name,1);
      }
    }
    // add monsters and health potions
    if (this.state.level===4) {
      addItemToMap("m",1);    // one boss
      addItemToMap("+",2);    // two health potions
    } else {
      addItemToMap("m",5);  //5 monsters, only one type on each level
      let numberOfHealthPotions = 5;
      addItemToMap("+",numberOfHealthPotions);
    }
    //all items added
    this.setState({map: testMap});
  }

  handleKeyEvent(e) {
    let keyNumber = e.keyCode;
    this.checkField(keyNumber);
  }

  checkField(keyNumber) {
    let x = this.state.heroX;
    let y = this.state.heroY;
    if (keyNumber===37) x--;
    if (keyNumber===38) y--;
    if (keyNumber===39) x++;
    if (keyNumber===40) y++;
    let fieldContent = this.state.map[y][x];
    /* Actions */
    // The hero found health potion
    if (fieldContent==="+") {
      let newHealth = this.state.heroHealth + 20;
      this.setState({
        heroHealth: newHealth,
        message: "You found a health potion (+20 health)."
        });
      }
    // the hero found weapon
    if (fieldContent==="w") {
      let newWeapon, newWeaponStr;
      for (let i=0;i<weapons.length;i++){
        if (weapons[i].x===x && weapons[i].y===y) {
          newWeapon = weapons[i].name;
          newWeaponStr = weapons[i].strength;
        }
      }
      let newMessage = "You found " + newWeapon + " (+" + newWeaponStr + " attack).";
      if (this.state.heroWeaponStrength<newWeaponStr) {
        this.setState({
          heroWeapon: newWeapon,
          heroWeaponStrength: newWeaponStr,
          message: newMessage
        });
      } else {
        this.setState({ message: "You found a weapon, but yours current weapon is better."});
      }
    }
    // hero's Actions
    let currentHeroHealth = this.state.heroHealth;
    // the hero met a monsters
    if (fieldContent==="m" || fieldContent==="B") {
      let turn = 0;
      let monsterHealth, monsterAttack, monsterName, monsterLevel;
      let heroAttack = this.state.heroWeaponStrength + this.state.heroLevel;
      let newMessage="";
      for (let i=0;i<monstersOnMap.length;i++){
        if (monstersOnMap[i].x===x && monstersOnMap[i].y===y) {
          monsterHealth = monstersOnMap[i].health;
          monsterAttack = monstersOnMap[i].attack;
          monsterName = monstersOnMap[i].name;
          monsterLevel = monstersOnMap[i].level;
        }
      }
      // battle
      newMessage = "You fought with the " + monsterName + ". ";
      while (currentHeroHealth>0 && monsterHealth>0)  {
        let randomHeroAttack = Math.floor(Math.random()*(heroAttack*0.5));
        let randomMonsterAttack = Math.floor(Math.random()*(heroAttack*0.5));
        currentHeroHealth -= monsterAttack+randomMonsterAttack;
        monsterHealth-= heroAttack+randomHeroAttack;
        turn++;
        newMessage+="Turn: "+turn+", Hero lost: "+(monsterAttack+randomMonsterAttack)+" , the "+monsterName+" lost: "+(heroAttack+randomHeroAttack)+". ";
      }
      if (currentHeroHealth>0) {
        newMessage+= "Hero won the battle.";
        let newExp = monsterLevel*5;
        let newHeroExp = parseInt(this.state.heroExperience)+newExp;
        /* hero defeated boss */
          if (fieldContent==="B"){
            newMessage+= "The boss is dead. You won the game!";
            this.setState({
              message: newMessage,
              endGame: true
            });
          }
        if (newHeroExp>=this.state.heroNextLevel) {
          // Hero level up
          let newExpAfterlevelUp = newHeroExp - this.state.heroNextLevel;
          let newLevel = this.state.level +1;
          let newLimit = newLevel*25; // linear increase new expiernce points
          newMessage+=" You increased your level to "+newLevel+" !!! ";
          this.setState({
            heroLevel: newLevel,
            heroExperience: newExpAfterlevelUp,
            heroHealth:currentHeroHealth,
            heroNextLevel: newLimit,
            message: newMessage
          });
        } else {
          this.setState({
            heroHealth:currentHeroHealth,
            heroExperience: newHeroExp,
            message: newMessage
          });
        }
      } else {
        newMessage+="The hero failed the battle and died."
        this.setState({
          heroHealth:currentHeroHealth,
          message: newMessage,
          endGame: true
        });
      }

    }
    let endGame = this.state.endGame;
    if (fieldContent!=="#" && endGame === false) this.move(keyNumber);
    if (fieldContent==="/") this.loadMap(this.state.level);
  }

move(keyNumber) {

    if (keyNumber===37) { //Left
    let changeRow1 = testMap[this.state.heroY].substr(0,this.state.heroX-1)+"H "+testMap[this.state.heroY].substr(this.state.heroX+1);
    testMap[this.state.heroY] = changeRow1;
    this.setState({
      heroX: this.state.heroX -1,
      map: testMap
    })
   }
  if (keyNumber===38) {  //Up
    let changeRow1 = testMap[this.state.heroY].substr(0,this.state.heroX)+" "+testMap[this.state.heroY].substr(this.state.heroX+1);
    let changeRow2 = testMap[this.state.heroY-1].substr(0,this.state.heroX)+"H"+testMap[this.state.heroY-1].substr(this.state.heroX+1);
    testMap[this.state.heroY] = changeRow1;
    testMap[this.state.heroY-1] = changeRow2;
    this.setState({
      heroY: this.state.heroY -1,
      map: testMap
    })
   }
   if (keyNumber===39) { //Right
     let changeRow1 = testMap[this.state.heroY].substr(0,this.state.heroX)+" H"+testMap[this.state.heroY].substr(this.state.heroX+2);
     testMap[this.state.heroY] = changeRow1;
     this.setState({
       heroX: this.state.heroX +1,
       map: testMap
     })
    }
    if (keyNumber===40) {  //Down
      let changeRow1 = testMap[this.state.heroY].substr(0,this.state.heroX)+" "+testMap[this.state.heroY].substr(this.state.heroX+1);
      let changeRow2 = testMap[this.state.heroY+1].substr(0,this.state.heroX)+"H"+testMap[this.state.heroY+1].substr(this.state.heroX+1);
      testMap[this.state.heroY] = changeRow1;
      testMap[this.state.heroY+1] = changeRow2;
      this.setState({
        heroY: this.state.heroY +1,
        map: testMap
      })
     }
}

toggleDarkness() {
  if (this.state.heroSeesAll) {
      this.setState({ heroSeesAll: false })
  } else {
    this.setState({ heroSeesAll: true})
  }
}

loadMap(mapLevel) {
  let newLevel = mapLevel+1;
  if (mapLevel===1) {
    testMap = level2.slice();
    this.setState({ map: level2,
    message: "You entered to temple's basement." });
  }
  if (mapLevel===2) {
    testMap = level3.slice();
    this.setState({ map: level3,
    message: "You entered to the cave under the temple." });
  }
  if (mapLevel===3) {
    testMap = level4.slice();
    this.setState({ map: level4,
    message: "You entered to the boss's chamber." });
  }
  this.setState({level: newLevel });
  this.addItemsToMap(newLevel);
}

reset() {
  monstersOnMap=[], monsterID=0; testMap=[];
  testMap = level1.slice();
  this.setState({
    map: testMap,
    level: 1,
    heroY: 38,
    heroX: 9,
    heroHealth: 100,
    heroLevel: 1,
    heroWeapon: "fist",
    heroWeaponStrength: 3,
    heroExperience: 0,
    heroNextLevel: 25,
    message: "Click anywhere and use arrows to move.",
    endGame: false
  },function(){ this.addItemsToMap(this.state.level) });
}

componentDidMount() {
  this.addItemsToMap(this.state.level);
  window.addEventListener("keydown", this.handleKeyEvent);
}

componentWillUnmount() {
  window.removeEventListener("keydown", this.handleKeyEvent);
}

render () {
  let hero = {
    heroHealth: this.state.heroHealth,
    heroLevel: this.state.heroLevel,
    heroWeapon: this.state.heroWeapon,
    heroWeaponStrength: this.state.heroWeaponStrength,
    heroExp: this.state.heroExperience,
    heroNextLevel: this.state.heroNextLevel,
    level: this.state.level,
  };

  let gameData = {
    heroY: this.state.heroY,
    heroX: this.state.heroX,
    heroSeesAll: this.state.heroSeesAll,
    message: this.state.message,
    endGame: this.state.endGame,
    toggleDarkness: this.toggleDarkness,
    reset: this.reset,
    endGame: this.state.endGame
  }


  return <Display map={this.state.map} hero={hero} gameData={gameData}/>;
  }
}

class Display extends React.Component {
  render() {
    const mapFromApp = this.props.map;
    let tempMap =[];
    let tempMapRow;
    let mapLengthY = mapFromApp.length;
    // displayed map is 17x23 chars (17 rows, 23 column)
    const displayedMapHeigth = 17;
    const mapWidth = 23;
    const fromHeroToSideBorders = 11;
    const fromHeroToTopBottomBorders = 8;
    const heroSeesAll = this.props.gameData.heroSeesAll;
    const heroY = this.props.gameData.heroY;
    const heroX = this.props.gameData.heroX;

    for (let i=0; i<displayedMapHeigth; i++) {
      let rowToPush="";
      let tempRowIndex = heroY-fromHeroToTopBottomBorders+1+i;
      if (tempRowIndex<0) {           //fill up empty top
        let emptyRow ="";
        for (let i=0; i<mapWidth; i++) {
          emptyRow+="."
        }
        tempMap.push(emptyRow);
      }
      if (tempRowIndex>=0 && tempRowIndex<mapLengthY) {
        tempMapRow = mapFromApp[tempRowIndex];
        let tempMapRowLength = tempMapRow.length;
        let indexInRow = heroX-fromHeroToSideBorders;
        let counter=0;
        while(indexInRow<0) {             // fill up empty left side
          rowToPush+=".";
          counter++;
          indexInRow++;
        }
        rowToPush += tempMapRow.substr(indexInRow, mapWidth-counter);
        if (indexInRow+fromHeroToSideBorders>=tempMapRowLength-fromHeroToSideBorders) { //fill up empty right side
          let charsNumberToAdd = indexInRow-tempMapRowLength+mapWidth;
          for (let i=0; i<charsNumberToAdd;i++){
            rowToPush+=".";
          }
        }
      }
      if (tempRowIndex>=mapLengthY) {             // fill up empty bottom
        let emptyRow ="";
        for (let i=0; i<mapWidth; i++) {
          emptyRow+="."
        }
        tempMap.push(emptyRow);
      }
      tempMap.push(rowToPush);
    }
    if (heroSeesAll===false) {          // darkness mask
      let limitedView=[];
      let leftside, rightside, middle;
      let correction = 0;
      if (heroY-fromHeroToTopBottomBorders-1<0) {
        correction = ((heroY-fromHeroToTopBottomBorders)*(-1))-1;
        for (let i=0; i<correction; i++) {
          tempMap.shift();
        }
      }
      for (let i=0; i<displayedMapHeigth; i++) {
        if (i===0 || i===16) {
          leftside="";
          middle = ".......................";
        }
        if(i===1 || i===15) {
          leftside=".........";
          middle = tempMap[i].substr(9,5) || ".....";
        }
        if (i==2 || i===14) {
          leftside = ".......";
          middle = tempMap[i].substr(7,9) || ".........";
        }
        if (i==3 || i===13) {
          leftside = "......";
          middle = tempMap[i].substr(6,11) || "...........";
        }
        if (i===4 || i===5 || i===12 || i===11) {
          leftside=".....";
          middle = tempMap[i].substr(5,13) || ".............";
        }
        if (i >= 6 && i<11) {
          leftside="....";
          middle = tempMap[i].substr(4,15) || "...............";
        }
        rightside=leftside;
        limitedView.push(leftside+middle+rightside);
      }
      tempMap = limitedView;
    }
    let key = 0;
    const rowList = tempMap.map((newRows) => 
        <pre key={key++}>{newRows}</pre>
      );

    let showMap = rowList;
    let heroDetails = this.props.hero;
    let buttonsData = {
      toggleDarkness: this.props.gameData.toggleDarkness,
      reset: this.props.gameData.reset,
      endGame: this.props.gameData.endGame
    }
    let messages = this.props.gameData.message;
    return (
      <div className="screen">
        <div className="left-column">
          <Logo />
          <Hero hero={heroDetails} />
          <Menu data={buttonsData} />
          <Key />
        </div>
        <div className="map">
         {showMap}
        </div>
        <MessageBox messages={messages} />
      </div>
    );
  }
}

class Logo extends React.Component {
  render() {
    return (
      <div className="logo-area">
        <h1>The Old Temple</h1>
        <h2>Rougelike Game</h2>
        <p className="small-signature">Created by Sebastian Sporek</p>
      </div>
    );
  }
}

class Hero extends React.Component {
  render() {
    return (
      <div className="hero-box">
        <ul className="list">
          <li>Dungeon:{this.props.hero.level}/4 </li>
          <li>Level:{this.props.hero.heroLevel}  Experience:{this.props.hero.heroExp}/{this.props.hero.heroNextLevel}</li>
          <li>Health:{this.props.hero.heroHealth}  Strength:{this.props.hero.heroLevel}</li>
          <li>Weapon:{this.props.hero.heroWeapon}(+{this.props.hero.heroWeaponStrength})</li>
        </ul>
      </div>
    );
  }
}

class Menu extends React.Component {
  render() {
    let resetButton;
    const endGame = this.props.data.endGame;
    if (endGame===true) {
      resetButton  = <button className="btn" type="button" onClick={this.props.data.reset}>Reset</button>;
    } else {
      resetButton= "";
    }
    return (
      <div className="menu">
        <button className="btn" onClick={this.props.data.toggleDarkness}>Toggle darkness</button>
          {resetButton}
      </div>

    );
  }
}

class Key extends React.Component {
  render() {
    return(
      <div className="key">
        <p> Kill all monsters in each dungeon. Collect all health potions and find a better
        weapon. Beware! If you go down by stairways, that you cannot go back. In the
        last dungeon kill the boss to win this game.</p>
        <p className="chars">The key: hero(H), move ({'\u2190 \u2191 \u2192 \u2193'}), wall(#), darkness(.),
          health potions(+), weapons(w), monsters(m), stairways(/)</p>
      </div>
    );
  }
}

class MessageBox extends React.Component {
  render() {
    return (
      <div className="message-box">
       {this.props.messages}
      </div>
    );
  }
}

ReactDOM.render(<App />, app);

            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.

Console