const reverseMap = { forward: 'backward', backward: 'forward', left: 'right', right: 'left' }; /** * Class determining player actions for warriorjs 'game' */ class Player { constructor() { this.warrior = null; this.direction = 'forward'; this.status = { _health: 20, health: 20, isHealing: false, damage: false }; this.adjacent = { forward: null, backward: null, left: null, right: 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.direction = this.warrior.directionOfStairs(); this.adjacent = { forward: this.warrior.feel('forward'), backward: this.warrior.feel('backward'), left: this.warrior.feel('left'), right: this.warrior.feel('right') }; } /** * 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; } } isNothingAdjacent() { let allClear = true; for (const dir in this.adjacent) { if ( ! (this.adjacent[dir].isEmpty() || this.adjacent[dir].isWall())) { return false; } } return allClear; } /** * Does an adjacent enemy exist? */ isEnemyInRange() { for (const dir in this.adjacent) { if (this.adjacent[dir].isEnemy()) { return true; } } return false; } /** * Determine if there are multiple adjacent enemies */ areMultipleEnemiesAdjacent() { let numEnemies = 0; for(const dir in this.adjacent) { if (this.adjacent[dir].isEnemy() { numEnemies++; } } return (numEnemies > 1); } /** * Return the direction of the first ajacent enemy found * * @return {string | boolean} */ findAdjacentEnemy() { let enemy = false; for (const dir in this.adjacent) { if (this.adjacent[dir].isEnemy()) { return dir; } } return false; } /** * 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) { // There are multiple adjacent enemies case this.areMultipleEnemiesAdjacent(): this.warrior.bind(this.findAdjacentEnemy()); break; // There's an adjacent enemy case this.isEnemyInRange(): this.warrior.attack(this.findAdjacentEnemy()); break; // Nothing directly adjacent case this.isNothingAdjacent(): // 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[direction]); } else { this.warrior.walk(direction); } 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.direction); // Save current health this.status._health = this.status.health; } }