182 lines
4.2 KiB
JavaScript
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;
|
||
|
}
|
||
|
}
|