tutorials/nodeJS/warriorjs/tom-beginner/Player.js

182 lines
4.2 KiB
JavaScript

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;
}
}