Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automated ship movement - searching for resources #93

Merged
merged 1 commit into from Aug 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
94 changes: 84 additions & 10 deletions automove.js
Expand Up @@ -19,6 +19,10 @@ let computer = {

telescopeHarbour: [],

telescopeResources: [],

bestDestination: [],

maxDistanceTiles: [],

minCostTiles: [],
Expand Down Expand Up @@ -101,9 +105,9 @@ let computer = {
if(workFlow == 1) {console.log('Damaged ship - decide move: '+ (Date.now() - launchTime)); }

computer.targetHarbour = pirates.findTarget('All', 'harbour');
if(workFlow == 1) {console.log('targetHarbour', computer.targetHarbour);}
if(arrayFlow == 1) {console.log('targetHarbour', computer.targetHarbour);}
computer.telescopeHarbour = pirates.useTelescope('All', 'harbour', maxMove);
if(workFlow == 1) {console.log('telescopeHarbour', computer.telescopeHarbour);}
if(arrayFlow == 1) {console.log('telescopeHarbour', computer.telescopeHarbour);}

if (computer.targetHarbour.length > 0) {
// 1 - Move to safe harbour within wind range
Expand Down Expand Up @@ -137,12 +141,26 @@ let computer = {
// Deciding move for undamaged ships (damageStatus is 5 for healthy ships)
} else if (pieceMovement.movementArray.start.pieces.damageStatus == 5) {
if(workFlow == 1) {console.log('Good ship - decide move: '+ (Date.now() - launchTime)); }
// Move maximum distance at minimum wind cost
if(workFlow == 1) {console.log('Finds max distance move at minimum cost: ' + (Date.now() - launchTime)); }
computer.maxDistanceTiles = pirates.maxPathDistance();
computer.minCostTiles = pirates.minArray(computer.maxDistanceTiles, 'moveCost');
computer.computerShipsTurn[computer.computerShipsTurnCount].end.row = computer.minCostTiles[0].row;
computer.computerShipsTurn[computer.computerShipsTurnCount].end.col = computer.minCostTiles[0].col;

computer.telescopeResources = pirates.useTelescope('All', 'resourceHarbour', row);
if(arrayFlow == 1) {console.log('telescopeResources', computer.telescopeResources);}

computer.bestDestination = computer.rankDestinations(computer.telescopeResources);

if (computer.bestDestination.length > 0) {
lastTile = pirates.findLastActive(pieceMovement.findPath[computer.bestDestination[0].row][computer.bestDestination[0].col].path, 0);
computer.computerShipsTurn[computer.computerShipsTurnCount].end.row = pieceMovement.findPath[computer.bestDestination[0].row][computer.bestDestination[0].col].path[lastTile].fromRow;
computer.computerShipsTurn[computer.computerShipsTurnCount].end.col = pieceMovement.findPath[computer.bestDestination[0].row][computer.bestDestination[0].col].path[lastTile].fromCol;

} else {
// Move maximum distance at minimum wind cost - should not be required if
if(workFlow == 1) {console.log('Finds max distance move at minimum cost: ' + (Date.now() - launchTime)); }
computer.maxDistanceTiles = pirates.maxPathDistance();
computer.minCostTiles = pirates.minArray(computer.maxDistanceTiles, 'moveCost');
console.log('computer.maxDistanceTiles', computer.maxDistanceTiles)
computer.computerShipsTurn[computer.computerShipsTurnCount].end.row = computer.minCostTiles[0].row;
computer.computerShipsTurn[computer.computerShipsTurnCount].end.col = computer.minCostTiles[0].col;
}

// Catching move for ships under repair (damageStatus between 0 and 5)
} else {
Expand Down Expand Up @@ -191,7 +209,6 @@ let computer = {

// Check whether there are resources to be claimed
for (var k = 0; k < computer.computerShipsTurn.length; k+=1) {

for (var i = -1; i < 2; i+=1) {
if(computer.computerShipsTurn[k].end.row+i >=0 && computer.computerShipsTurn[k].end.row+i <row) {
for (var j = -1; j < 2; j+=1) {
Expand All @@ -218,7 +235,7 @@ let computer = {

// Decide whether a resource should be claimed - simple version of decision for first implementation
for (var l = 0; l < claimableResources.length; l+=1) {
// Need to check whether player has already claimed this resource in this loop - can happen that claimableResource includes 2 or 3 of same resource type
// Need to check whether player has already claimed this resource in this loop - can happen that claimableResource includes 2 or 3 of same resource type
if (stockDashboard.pieceTotals[teamPosition].pieces[claimableResources[l].type].quantity == 0) {
// Claim resource (already checked that have resource in construction of claimable resource)
resourceManagement.claimResource(claimableResources[l].row, claimableResources[l].col, gameManagement.turn);
Expand All @@ -229,6 +246,63 @@ let computer = {
}
},

// Method to rank potential map destinations for move choice related to Resources
// ------------------------------------------------------------------------------
// TO DO: add / subtract points for (a) Nearness to next good option (b) Closeness to pirates ships
// Also need to consider moving off route for lesser detination if its on the way to best destination
rankDestinations: function(movesToRate) {
// Team position of piece information array required to check if resource pieces already held
let teamPosition = stockDashboard.pieceTotals.findIndex(fI => fI.team == gameManagement.turn);
let maxPoints = 0;
let bestMove = [];

// Loops through all potential map moves and adds points to rate them
for (var i = 0; i < movesToRate.length; i+=1) {
movesToRate[i].points = 0;
if(movesToRate[i].pathStop[0] == 'none' || movesToRate[i].activeStatus != 'active') {
for (var j = 0; j < movesToRate[i].type.length; j+=1) {
// Virgin islands are worth visiting - and a better option if they can be reached in one turn
if(movesToRate[i].type[j] == 'virgin') {
if(movesToRate[i].activeStatus == 'active') {
movesToRate[i].points += 3;
} else {
movesToRate[i].points += 1;
}
// Revealed pieces that are needed are more valuable options than virgin islands which may be desert or duplicate pieces
} else if (stockDashboard.pieceTotals[teamPosition].pieces[movesToRate[i].type[j]].quantity == 0) {
if(movesToRate[i].activeStatus == 'active') {
movesToRate[i].points += 6;
} else {
movesToRate[i].points += 4;
}
} else {
// no points
}
}

// Points for destinations at greater distance are reduced by estimated number of moves to get there
let moveCostDivisor = 1;
if (movesToRate[i].activeStatus == 'active') {
// moveCostDivisor = 1;
} else {
moveCostDivisor = movesToRate[i].moveCost/maxMove;
}
movesToRate[i].points = Number((movesToRate[i].points / moveCostDivisor).toFixed(2));

// Array built up of highest scoring options
if (movesToRate[i].points > maxPoints) {
maxPoints = movesToRate[i].points
bestMove = [movesToRate[i]];
} else if (movesToRate[i].points == maxPoints && movesToRate[i].points > 0) {
bestMove.push(movesToRate[i]);
}
}
}

if(arrayFlow == 1) {console.log('bestMove', bestMove);}
return bestMove;
},


// LAST BRACKET OF OBJECT
}
2 changes: 1 addition & 1 deletion main.js
Expand Up @@ -468,7 +468,7 @@ function boardHandler(event) {
}

// Loading of a ship
} else if (((pieceMovement.movementArray.start.pieces.category == 'Resources' && pieceMovement.movementArray.start.pieces.type != 'desert') || pieceMovement.movementArray.start.pieces.category == 'Settlements') && pieceMovement.movementArray[startEnd].pieces.team == gameManagement.turn) {
} else if (((pieceMovement.movementArray.start.pieces.category == 'Resources' && pieceMovement.movementArray.start.pieces.type != 'desert') || pieceMovement.movementArray.start.pieces.category == 'Settlements') && pieceMovement.movementArray[startEnd].pieces.team == gameManagement.turn) {
if (pieceMovement.shipAvailable(pieceMovement.movementArray.start.pieces.goods) == 'compatible') {
if (pieceMovement.movementArray.start.pieces.stock > 0) {
startEnd = 'end';
Expand Down
52 changes: 42 additions & 10 deletions movement.js
Expand Up @@ -54,7 +54,7 @@ let pieceMovement = {
if(localStartCol+j >=0 && localStartCol+j <col) {
// Checks if tile is found. If so runs activeTiles to search for potential tiles to activate around it.
// Does not check tiles if pathStop is active (pathStop prevents ships moving through harbours or other ships)
if ((this.findPath[localStartRow+i][localStartCol+j].pathStatus == true) && (this.findPath[localStartRow+i][localStartCol+j].pathStop.type == 'none' || k == 0)) {
if ((this.findPath[localStartRow+i][localStartCol+j].pathStatus == true) && (this.findPath[localStartRow+i][localStartCol+j].pathStop.type[0] == 'none' || k == 0)) {
//Keep useful for debugging - console.log('run: ' + k);
//Keep useful for debugging - console.log('starting from: row: ' + (localStartRow+i) + ' col: ' + (localStartCol+j) + ' prior cost: ' + this.findPath[localStartRow+i][localStartCol+j].moveCost);
this.activeTiles(localStartRow+i, localStartCol+j, this.findPath[localStartRow+i][localStartCol+j].moveCost, localMaxMove, displayActive, k, localDamagedStatus);
Expand All @@ -80,7 +80,7 @@ let pieceMovement = {
for (var i = 0; i < col; i++) {
let localMoveRow = [];
for (var j = 0; j < row; j++) {
localMoveRow[j] = {pathStatus: false, activeStatus: 'inactive', moveCost: 0, distance: 0, target: {type: 'none', team: 'none'}, harbour: {type: 'none', team: 'none'}, pathStop: {type: 'none', team: 'none'}, path: [{fromRow: +localStartRow , fromCol: +localStartCol}]};
localMoveRow[j] = {pathStatus: false, activeStatus: 'inactive', moveCost: 0, distance: 0, target: {type: ['none'], team: 'none'}, resourceHarbour: {type: ['none'], team: 'none'}, harbour: {type: ['none'], team: 'none'}, pathStop: {type: ['none'], team: 'none'}, path: [{fromRow: +localStartRow , fromCol: +localStartCol}]};
}
this.findPath[i] = localMoveRow;
}
Expand Down Expand Up @@ -131,7 +131,7 @@ let pieceMovement = {
// Keep useful for debugging - console.log('already active logic is used:');
//console.log('change to active tile - pre:', localStartRow+i, localStartCol+j, this.findPath[localStartRow+i][localStartCol+j], 'from ' + localStartRow + '-' + localStartCol, this.findPath[localStartRow][localStartCol]);
// Update the cost, add the inherited path from the previous moved-to tile, push the path for the new tile
this.findPath[localStartRow+i][localStartCol+j].moveCost = tileCumulMoveCost;
this.findPath[localStartRow+i][localStartCol+j].moveCost = Number(tileCumulMoveCost.toFixed(2));
this.findPath[localStartRow+i][localStartCol+j].path = this.findPath[localStartRow][localStartCol].path.slice(0);
this.findPath[localStartRow+i][localStartCol+j].path.push({fromRow: +(localStartRow+i) , fromCol: +(localStartCol+j)});
this.findPath[localStartRow+i][localStartCol+j].distance = this.findPath[localStartRow+i][localStartCol+j].path.length-1;
Expand All @@ -149,7 +149,7 @@ let pieceMovement = {
}
}
// Update the cost, add the inherited path from the previous moved-to tile, push the path for the new tile
this.findPath[localStartRow+i][localStartCol+j].moveCost = tileCumulMoveCost;
this.findPath[localStartRow+i][localStartCol+j].moveCost = Number(tileCumulMoveCost.toFixed(2));

this.findPath[localStartRow+i][localStartCol+j].path = this.findPath[localStartRow][localStartCol].path.slice(0);
this.findPath[localStartRow+i][localStartCol+j].path.push({fromRow: +(localStartRow+i) , fromCol: +(localStartCol+j)});
Expand Down Expand Up @@ -190,20 +190,52 @@ let pieceMovement = {
for (var j = 0; j < row; j++) {
// Target transport ships for pirate attack
if (gameBoard.boardArray[i][j].pieces.category == 'Transport' && gameBoard.boardArray[i][j].pieces.team != 'Pirate' && gameBoard.boardArray[i][j].pieces.damageStatus == 5) {
this.findPath[i][j].target = {type: gameBoard.boardArray[i][j].pieces.type, team: gameBoard.boardArray[i][j].pieces.team};
this.findPath[i][j].target = {type: [gameBoard.boardArray[i][j].pieces.type], team: gameBoard.boardArray[i][j].pieces.team};
}
// Unclaimed resources and virgin islands harbour
if ( (gameBoard.boardArray[i][j].terrain == 'land' && !gameBoard.boardArray[i][j].pieces.populatedSquare) ||
(gameBoard.boardArray[i][j].pieces.category == 'Resources' && gameBoard.boardArray[i][j].pieces.type != 'desert' && gameBoard.boardArray[i][j].pieces.team == 'Unclaimed') ) {
// Single tile search around the island
for (var k = -1; k < 2; k+=1) {
if(i + k >=0 && i + k <row) {
for (var l = -1; l < 2; l+=1) {
if(j + l >=0 && j + l <col) {
// Reduces search to exclude diagonals
if(k == 0 || l == 0) {
if(gameBoard.boardArray[i+k][j+l].terrain == 'sea') {
if(this.findPath[i+k][j+l].resourceHarbour.type[0] == 'none') {
if (gameBoard.boardArray[i][j].pieces.category == 'Resources' && gameBoard.boardArray[i][j].pieces.type != 'desert' && gameBoard.boardArray[i][j].pieces.team == 'Unclaimed') {
this.findPath[i+k][j+l].resourceHarbour.type[0] = gameBoard.boardArray[i][j].pieces.type;
} else {
this.findPath[i+k][j+l].resourceHarbour.type[0] = 'virgin';
}
} else {
if (gameBoard.boardArray[i][j].pieces.category == 'Resources' && gameBoard.boardArray[i][j].pieces.type != 'desert' && gameBoard.boardArray[i][j].pieces.team == 'Unclaimed') {
this.findPath[i+k][j+l].resourceHarbour.type.push(gameBoard.boardArray[i][j].pieces.type);
} else {
this.findPath[i+k][j+l].resourceHarbour.type.push('virgin');
}
}
}
}
}
}
}
}
}
// Safe harbour for ship repair or hiding
if (gameBoard.boardArray[i][j].subTerrain == 'harbour') {
this.findPath[i][j].harbour = {type: gameBoard.boardArray[i][j].subTerrain, team: 'none'};
this.findPath[i][j].harbour = {type: [gameBoard.boardArray[i][j].subTerrain], team: 'none'};
}
// Tiles where path must end
if (gameBoard.boardArray[i][j].pieces.category == 'Transport') {
this.findPath[i][j].pathStop = {type: gameBoard.boardArray[i][j].pieces.type, team: gameBoard.boardArray[i][j].pieces.team};
this.findPath[i][j].pathStop = {type: [gameBoard.boardArray[i][j].pieces.type], team: gameBoard.boardArray[i][j].pieces.team};
} else if (gameBoard.boardArray[i][j].subTerrain == 'harbour') {
this.findPath[i][j].pathStop = {type: gameBoard.boardArray[i][j].subTerrain, team: 'none'};
this.findPath[i][j].pathStop = {type: [gameBoard.boardArray[i][j].subTerrain], team: 'none'};
}
}
}
if(arrayFlow == 1) {console.log('findPath', this.findPath);}
},

// Sets the "cost" of each move in relation to the wind direction
Expand All @@ -227,6 +259,7 @@ let pieceMovement = {
moveCostResult = 0.8;
}
return moveCostResult;

},

// Method to deactivate tiles after a piece has moved
Expand Down Expand Up @@ -600,8 +633,7 @@ let pieceMovement = {
let endCannon = 0;
if (pirates.conflictArray.conflict == true) {
if(workFlow == 1) {console.log('Ship conflict - battle: ' + (Date.now() - launchTime)); }
console.log(pirates.conflictArray);
console.log(startDirection);
if(arrayFlow == 1) {console.log('conflictArray', pirates.conflictArray);}
// Obtains ID and element of pirates
IDPirate = 'tile' + Number(pirates.conflictArray.pirate.row*1000 + pirates.conflictArray.pirate.col);
let piratePiece = document.getElementById(IDPirate);
Expand Down