166 lines
3.3 KiB
JavaScript
166 lines
3.3 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.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;
|
|
}
|
|
}
|