const reverseMap = { forward: 'backward', backward: 'forward', left: 'right', right: 'left' }; /** * Class determining player actions for warriorjs 'game' */ class Player { constructor() { this.warrior = null; this.status = { _health: 20, health: 20, isHealing: false, damage: false, direction: 'forward', space: null }; } /** * Collect information about the world for the Turn */ sense() { this.status.health = this.warrior.health(); // Health of current turn this.status.damage = (this.status._health > this.status.health); this.status.space = this.warrior.feel(this.status.direction); } /** * Determine if the adjacent spaces are empty * * @param {String} direction * @return {Space | boolean} */ isNotEmptyInSight(direction) { return this.warrior.look(direction).find(space => ! space.isEmpty()); } /** * See if there is an enemy within sight * * @param {String} direction * @return {boolean} */ isEnemyInSight(direction) { const space = this.isNotEmptyInSight(direction); return space && space.isEnemy(); } /** * See if the wall is in sight * * @param {String} direction * @return {boolean} */ isWallInSight(direction) { const space = this.isNotEmptyInSight(direction); return space && space.isWall(); } /** * See if a captive is in sight * * @param {String} direction * @return {boolean} */ isCaptiveInSight(direction) { const space = this.isNotEmptyInSight(direction); return space && space.isCaptive(); } /** * Check if you can see the stairs * * @param {String} direction * @return {boolean} */ areStairsInSight(direction) { const space = this.warrior.look(direction).find(space => space.isStairs()); return Boolean(space); } /** * Logic for resting to gain health */ heal() { if (this.status.isHealing === false) { this.status.isHealing = true; } this.warrior.rest(); // Stop healing when at penultimate heath level // or if taking damage if (this.status.health >= 18 || this.status.damage) { this.status.isHealing = false; } } /** * Reverse direction and pivot */ turnAround() { const newDirection = reverseMap[this.status.direction]; this.status.direction = newDirection; this.warrior.pivot(newDirection); } /** * Determine what to do based on what you've found with the senses * * @param direction - The direction to go for the next turn */ next(direction) { switch(true) { case this.status.space.isWall(): this.turnAround(); break; case this.status.space.isEnemy(): this.warrior.attack(direction); break; case this.status.space.isCaptive(): this.warrior.rescue(direction); break; // Empty space default: // Check health (From 0 to 20) if ( ! this.status.damage && (this.status.health <= 16 || this.status.isHealing === true)) { this.heal(); } else if (this.status.damage && this.status.health <= 12) { // Low health and taking damage // Retreat to be able to heal this.warrior.walk(reverseMap[this.status.direction]); } else { // Determine what to do based on what you can see switch(true) { // Take care of the enemy behind you case this.isEnemyInSight(reverseMap[direction]): this.warrior.shoot(reverseMap[direction]); break; // Take care of the enemy in front of you case this.isEnemyInSight(direction): this.warrior.shoot(direction); break; // After taking care of enemies, look behind // to see if you should turn around because of a // wall, or if you need to rescue some captives case ( ! this.areStairsInSight(direction)) && this.isWallInSight(direction): case this.isCaptiveInSight(reverseMap[direction]): this.turnAround(); break; // On to the next space! default: this.warrior.walk(direction); break; } } break; } } /** * Callback for each Turn * * @param warrior - The player object */ playTurn(warrior) { // Save the warrior object for other methods this.warrior = warrior; // Examine the world this.sense(); // Figure out what to do with the next space this.next(this.status.direction); // Save current health this.status._health = this.status.health; } }