I am trying to make a game in vue js where i have tank, dps and healer
data: {
tankHealth: 100,
healerHealth: 100,
dpsHealth: 100,
monsterHealth: 200,
gameRunning: false,
turns: [],
},
I have a button that when it gets clicked it enters a setinterval function where every 1 second the tank and dps attack the monster. and the healer heals one of the players. But when it comes to monster attacking the player, i want the monster to attack randomly one of the players like that:
var monsterDamage = self.calculateDamage(10,20); // returns a random number between 10 and 20
var number = self.randomNumberFn(1,3);
// get a random number here so i can randomly pick a player to attack
switch(number) {
case 1:
self.dpsHealth -= monsterDamage;
if(self.dpsHealth <= 0) {
self.dpsHealth = 0;
break;
}
break;
case 2:
self.tankHealth -= monsterDamage;
if(self.tankHealth <= 0) {
self.tankHealth = 0;
break;
}
break;
case 3:
self.healerHealth -= monsterDamage;
if(self.healerHealth <= 0) {
self.healerHealth = 0;
break;
}
break;
}
The problem comes when one of the players is dead. In that case, I want the monster to attack only the players that are alive. In the model i have right now, even if one of the players is dead the monster keeps attacking him
Maybe like this?
do {
var n1 = 1;
var n2 = 3;
var monsterDamage = self.calculateDamage(10, 20);
var number = self.randomNumberFn(n1, n2);
switch (number) {
case 1:
if (self.dpsHealth === 0) { // === checks type too...
n1 = 2;
continue;
}
self.dpsHealth = doDamage(self.dpsHealth, monsterDamage);
break;
case 2:
if (self.dpsHealth === 0) {
continue;
}
self.tankHealth = doDamage(self.tankHealth, monsterDamage);
break;
case 3:
if (self.dpsHealth === 0) {
n2 = 2;
continue;
}
self.healerHealth = doDamage(self.healerHealth, monsterDamage);
break;
}
} while((self.dpsHealth + self.tankHealth + self.healerHealth) === 0)
function doDamage(health, damage) {
if ((health - damage) <= 0) {
return 0;
} else {
return health - damage;
}
}
To solve this problem, you can create an array to hold your living humans, and iterate through said array for a random value.
let livingHumans = [];
if(dpsHealth > 0) {
livingHumans.push({name:'dpsHealth', health:dpsHealth});
}
if(tankHealth > 0) {
livingHumans.push({name:'tankHealth', health:tankHealth});
}
if(healerHealth > 0) {
livingHumans.push({name:'healerHealth', health:healerHealth});
}
// get random value from array
let number = self.randomNumber(1, livingHumans.length)
// once you receive the output,
// you can use the name property to find the player in your object.
name = livingHumans[number].name;
console.log(data[name]);
Related
I've been working on writing a minimax algorithm for my tictactoe game, but it doesn't seem to be choosing the correct move. It is possible to win against the computer, so I must have something mixed up here.
I based my algorithm off this article (I had to alter my minimax code since my code was different from the example in the article)
// Checking if there are any moves remaining on the board. Returns false if there are no moves left to play
const isMovesLeft = function () {
if (gameBoard._moves === 9) {
return false;
} else {
return true;
}
};
// Evaluates if the maximiser or minimiser has won or draw - returns a number if there is a win or draw
const evaluate = function () {
if (gameBoard._roundWon && gameBoard._currentPlayer === gameBoard._player1)
return +10;
if (gameBoard._roundWon && gameBoard._currentPlayer === gameBoard._player2)
return -10;
if (gameBoard._roundTie) return 0;
};
// Minimax function - considers all the possible ways the game can go and returns the value of the board
const minimax = function (board, depth, isMax) {
let score = evaluate();
// If maximiser has won the game - return evaluated score
if (score === 10) return score;
// If minimiser has won the game - return evaluated score
if (score === -10) return score;
// If there are no moves left and there is no winner - then return as a tie
if (isMovesLeft() === false) return 0;
// If it is the maximiser's turn
if (isMax) {
let bestScore = -1000;
let availableTiles = [];
// Looping through all tiles
tile.forEach((tile, index) => {
// Check if cell is empty
if (tile.textContent === '') {
availableTiles.push(index);
}
});
// Make the move
const chosenEmptyTile =
availableTiles[Math.floor(Math.random() * availableTiles.length)];
renderAITile(tile, chosenEmptyTile);
addPlayerMoves(chosenEmptyTile);
// Calling minimax recursively and choose the maximum value
bestScore = Math.max(bestScore, minimax(board, depth + 1, false));
console.log(bestScore);
// Undo the move
undoAIMove(tile, chosenEmptyTile);
return bestScore;
} else {
let bestScore = 1000;
let availableTiles = [];
// Looping through all tiles
tile.forEach((tile, index) => {
// Check if cell is empty
if (tile.textContent === '') {
availableTiles.push(index);
}
});
// Make the move
const chosenEmptyTile =
availableTiles[Math.floor(Math.random() * availableTiles.length)];
renderAITile(tile, chosenEmptyTile);
addPlayerMoves(chosenEmptyTile);
// Calling minimax recursively and choose the maximum value
bestScore = Math.min(bestScore, minimax(board, depth + 1, false));
// Undo the move
undoAIMove(tile, chosenEmptyTile);
return bestScore;
}
};
const undoAIMove = function (tile, chosenEmptyTile) {
tile[chosenEmptyTile].textContent = '';
tile[chosenEmptyTile].classList.remove(`playerX`);
tile[chosenEmptyTile].classList.remove(`playerO`);
gameBoard._board[chosenEmptyTile] = '';
gameBoard._moves -= 1;
};
// Return the best possible move for the AI
const findBestMove = function (board) {
let bestVal = -1000;
let bestMove = [];
let availableTiles = [];
// Traverse all cells, evaluate minimax function for all empty cells. And return the cell with optimal value.
tile.forEach((tile, index) => {
if (tile.textContent === '') {
availableTiles.push(index);
}
});
// Make the move
console.log(`Empty Tile: ${availableTiles}`);
const chosenEmptyTile =
availableTiles[Math.floor(Math.random() * availableTiles.length)];
console.log(`Chosen tile: ${chosenEmptyTile}`);
renderAITile(tile, chosenEmptyTile);
addPlayerMoves(chosenEmptyTile);
console.log(gameBoard._board);
// Compute evaluation function for this move
let moveVal = minimax(board, 0, false);
// Undo the move
undoAIMove(tile, chosenEmptyTile);
// If value of the current move is more than the best value, then update best
if (moveVal > bestVal) {
bestVal = moveVal;
bestMove.push(chosenEmptyTile);
gameBoard._board[chosenEmptyTile] = 'X';
renderAITile(tile, bestMove);
}
return bestMove;
};
const startGameAI = function () {
if (gameBoard._aiTurn && gameBoard._opponent === 'AI') {
// Finding best move
findBestMove(gameBoard._board);
// Store AI moves in data
addPlayerMoves();
console.log(gameBoard._moves);
// Check if game over or tie
checkGameOver();
// Switch players
switchPlayers();
renderScoreBoard();
}
};
// Renders the tile AI selects
const renderAITile = function (tile, randomEmptyTileIndex) {
if (gameBoard._roundWon || gameBoard._roundTie || !gameBoard._isGameActive)
return;
if (gameBoard._aiTurn) {
tile[randomEmptyTileIndex].textContent = 'X';
tile[randomEmptyTileIndex].classList.add(
`player${gameBoard._currentPlayer}`
);
}
};
Full code on Codepen
My goal is to code a somewhat OK chess engine, in the following position it's a mate in 2 which the engine should easily find with its depth of 4-5.
The first move the AI makes is Ra2 to trap the white king, the white king goes to f1 and instead of mating the AI moves the Rook to c2.
var initial_depth = depth;
var bestMove = null;
var nodes = 0;
var ret = await minimax(position, depth, alpha, beta, maximizingPlayer);
console.log("nodes visited: " + nodes);
return ret;
async function minimax(position, depth, alpha, beta, maximizingPlayer) {
nodes++;
if (maximizingPlayer) {
var validMoves = await getValidMoves(position, ArrtoFEN(position) + " w");
} else {
var validMoves = await getValidMoves(position, ArrtoFEN(position) + " b");
}
if (validMoves.length < 1 || depth == 0) {
var eval = await getEval(position);
return [eval, null];
}
if (maximizingPlayer) {
var maxEval = Number.NEGATIVE_INFINITY;
for (var i = 0; i < validMoves.length; i++) {
var move = validMoves[i];
var testbrd = makeMove(move, position) //not the actual code. shortend for Readability
var eval = await minimax(testbrd, depth - 1, alpha, beta, false);
if (eval[0] > maxEval) {
maxEval = eval[0];
if (initial_depth == depth) {
bestMove = move;
console.log("current bestmove: " + bestMove);
}
}
alpha = Math.max(alpha, eval[0]);
if (beta <= alpha) {
break;
}
}
return [maxEval, bestMove];
} else {
var minEval = Number.POSITIVE_INFINITY;
for (var i = 0; i < validMoves.length; i++) {
var move = validMoves[i];
var testbrd = makeMove(move, position)//not the actual code. shortend for Readability
var eval = await minimax(testbrd, depth - 1, alpha, beta, true);
if (eval[0] < minEval) {
minEval = eval[0];
if (initial_depth == depth) {
bestMove = move;
console.log("current bestmove: " + bestMove);
}
}
beta = Math.min(beta, eval[0]);
if (beta <= alpha) {
break;
}
}
return [minEval, bestMove];
}
}
}
This is because it sees that any move will win, and you don't have a condition that tells the engine that it is better to do mate in 1 move than in 5 moves. If at the end of a search find that you have 0 legal moves and you are in check, then you are checkmated. In this case you want to send back a checkmate score (large negative value) and add the ply from this. This way you will make it better to mate in fewer moves than in a larger amount of moves.
I suggest you go for Negamax alogirthm in stead of minimax. It will mean much less code and much easier to debug.
Tried to make a script like this:
let intervals = [],
isClick = [],
isGameOver = false,
countElement = 3,
count = 0,
gameOver = function () {
if (isGameOver) {
return;
}
isGameOver = true;
if (countElement <= count) {
for (var i = 0; i < intervals.legth; ++i) {
clearInterval(intervals[i]);
}
intervals = [];
countElement = 0;
}
},
elm = function (index) {
return function () {
if (isGameOver || isClick[index]) {
return null;
}
isClick[index] = true;
clearInterval(intervals[index]);
intervals[index] = null;
if (!intervals.filter(a => a).length) {
count = countElement;
gameOver();
return;
}
};
};
for (let i = 0; i < 17; ++i) {
setTimeout(() => {
element.on('pointerup', elm(i));
intervals[i] = setInterval(() => {
if (countElement <= count) {
clearInterval(intervals[i]);
gameOver();
return;
}
if (-64 > element.position.y) {
clearInterval(intervals[i]);
intervals[i] = null;
++count;
} else {
element.position.y -= 30;
}
}, pos.speed);
}, pos.startTime * i);
}
It actually works, but for some reason it doesn't always work as it should.
Perhaps I'll tell you right away what is required ..
It is necessary to generate the required number of elements and move along the axis Y.
They must have different speeds.
I tried to solve it like this:
let rnd = function (min, max) {
return Math.floor(Math.random() * (max - min) + min);
}, pos = {
speed: Math.floor(rnd(100, rnd(370, 470))),
startTime: Math.floor(rnd(rnd(370, 470), rnd(700, 1000)))
}
In general, I would like to see the elements start flying with different departure and flight speeds, there were attempts that can be missed if the element flew away, when you click on the element, it stops.
Well, in fact, if all the elements flew out - it doesn't matter if they flew away or stopped, the main thing is that all intervals should stop and there would be a kind of exit ...
Connoisseurs help out how this can be done without third-party libraries?
How to do it correctly, please show.
Problem solved...
There was no need to zero out countElement and intervals in gameOver.
Because of this, subsequent intervals were looped, as the indices were violated.
I'm writing code for processing ANSI escape codes for cursor for jQuery Terminal. but have problems, not sure how it should work, I've got weird results.
I'm testing with ervy library.
and using this code:
function scatter_plot() {
const scatterData = [];
for (let i = 1; i < 17; i++) {
i < 6 ? scatterData.push({ key: 'A', value: [i, i], style: ervy.fg('red', '*') })
: scatterData.push({ key: 'A', value: [i, 6], style: ervy.fg('red', '*') });
}
scatterData.push({ key: 'B', value: [2, 6], style: ervy.fg('blue', '# '), side: 2 });
scatterData.push({ key: 'C', value: [0, 0], style: ervy.bg('cyan', 2) });
var plot = ervy.scatter(scatterData, { legendGap: 18, width: 15 });
// same as Linux XTERM where 0 code is interpreted as 1.
var formatting = $.terminal.from_ansi(plot.replace(/\x1b\[0([A-D])/g, '\x1b[1$1'));
return formatting;
}
$.terminal.defaults.formatters = [];
var term = $('body').terminal();
term.echo(scatter_plot());
it should look like in Linux Xterm:
But it looks like this, see codepen demo
While I was writing the question changing few +1 and -1 (see processing A-F ANSI escapes in the code) when moving cursor give this result (code snippet have latest code).
First line got overwritten by spaces and whole plot is one to top and one to right (except 0,0 cyan dot that should be below " |" and 2 characters wide, so you should see right half of it, this one is correct but the rest is not)
this is my new code for processing cursor, I'm doing this just before processing colors, so the code is not that complex.
// -------------------------------------------------------------------------------
var ansi_re = /(\x1B\[[0-9;]*[A-Za-z])/g;
var cursor_re = /(.*)\r?\n\x1b\[1A\x1b\[([0-9]+)C/;
var move_cursor_split = /(\x1b\[[0-9]+[A-G])/g;
var move_cursor_match = /^\x1b\[([0-9]+)([A-G])/;
// -------------------------------------------------------------------------------
function parse_ansi_cursor(input) {
/*
(function(log) {
console.log = function(...args) {
if (true || cursor.y === 11) {
return log.apply(console, args);
}
};
})(console.log);
*/
function length(text) {
return text.replace(ansi_re, '').length;
}
function get_index(text, x) {
var splitted = text.split(ansi_re);
var format = 0;
var count = 0;
var prev_count = 0;
for (var i = 0; i < splitted.length; i++) {
var string = splitted[i];
if (string) {
if (string.match(ansi_re)) {
format += string.length;
} else {
count += string.length;
if (count >= x) {
var rest = x - prev_count;
return format + rest;
}
prev_count = count;
}
}
}
return i;
}
// ansi aware substring, it just and add removed ansi escapes
// at the beginning we don't care if the were disabled with 0m
function substring(text, start, end) {
var result = text.substring(start, end);
if (start === 0 || !text.match(ansi_re)) {
return result;
}
var before = text.substring(0, start);
var match = before.match(ansi_re);
if (match) {
return before.match(ansi_re).join('') + result;
}
return result;
}
// insert text at cursor position
// result is array of splitted arrays that form single line
function insert(text) {
if (!text) {
return;
}
if (!result[cursor.y]) {
result[cursor.y] = [];
}
var index = 0;
var sum = 0;
var len, after;
function inject() {
index++;
if (result[cursor.y][index]) {
result[cursor.y].splice(index, 0, null);
}
}
if (cursor.y === 11) {
//debugger;
}
if (text == "[46m [0m") {
//debugger;
}
console.log({...cursor, text});
if (cursor.x === 0 && result[cursor.y][index]) {
source = result[cursor.y][0];
len = length(text);
var i = get_index(source, len);
if (length(source) < len) {
after = result[cursor.y][index + 1];
if (after) {
i = get_index(after, len - length(source));
after = substring(after, i);
result[cursor.y].splice(index, 2, null, after);
} else {
result[cursor.y].splice(index, 1, null);
}
} else {
after = substring(source, i);
result[cursor.y].splice(index, 1, null, after);
}
} else {
var limit = 100000; // infite loop guard
var prev_sum = 0;
// find in which substring to insert the text
while (index < cursor.x) {
if (!limit--) {
warn('[WARN] To many loops');
break;
}
var source = result[cursor.y][index];
if (!source) {
result[cursor.y].push(new Array(cursor.x - prev_sum).join(' '));
index++;
break;
}
if (sum === cursor.x) {
inject();
break;
}
len = length(source);
prev_sum = sum;
sum += len;
if (sum === cursor.x) {
inject();
break;
}
if (sum > cursor.x) {
var pivot = get_index(source, cursor.x - prev_sum);
var before = substring(source, 0, pivot);
var end = get_index(source, length(text));
after = substring(source, pivot + end);
if (!after.length) {
result[cursor.y].splice(index, 1, before);
} else {
result[cursor.y].splice(index, 1, before, null, after);
}
index++;
break;
} else {
index++;
}
}
}
cursor.x += length(text);
result[cursor.y][index] = text;
}
if (input.match(move_cursor_split)) {
var lines = input.split('\n').filter(Boolean);
var cursor = {x: 0, y: -1};
var result = [];
for (var i = 0; i < lines.length; ++i) {
console.log('-------------------------------------------------');
var string = lines[i];
cursor.x = 0;
cursor.y++;
var splitted = string.split(move_cursor_split).filter(Boolean);
for (var j = 0; j < splitted.length; ++j) {
var part = splitted[j];
console.log(part);
var match = part.match(move_cursor_match);
if (match) {
var ansi_code = match[2];
var value = +match[1];
console.log({code: ansi_code, value, ...cursor});
if (value === 0) {
continue;
}
switch (ansi_code) {
case 'A': // UP
cursor.y -= value;
break;
case 'B': // Down
cursor.y += value - 1;
break;
case 'C': // forward
cursor.x += value + 1;
break;
case 'D': // Back
cursor.x -= value + 1;
break;
case 'E': // Cursor Next Line
cursor.x = 0;
cursor.y += value - 1;
break;
case 'F': // Cursor Previous Line
cursor.x = 0;
cursor.y -= value + 1;
break;
}
if (cursor.x < 0) {
cursor.x = 0;
}
if (cursor.y < 0) {
cursor.y = 0;
}
} else {
insert(part);
}
}
}
return result.map(function(line) {
return line.join('');
}).join('\n');
}
return input;
}
The result = []; in code is array of lines where single line may be split into multiple sub strings when inserting the text at cursor, maybe the code would be simpler if they would be array of strings. Right now I want only fix the cursor position.
Here is the codepen demo with from_ansi function embeded (inside there is parse_ansi_cursor that is problematic). Sorry there is lot of code, but parsing ANSI escape codes is not simple.
What I'm not sure how should work is moving the cursor (right now it have + 1 or - 1, I'm not sure about this) I'm also not sure if I should increase cursor.y before each line. I'm not 100% sure how this should work. I've looked into Linux Xterm code but didn't found a clues. Looked at Xterm.js but the ervy plot is completely broken for those scatter plot.
my from_ansi function had original code that was processing some ANSI cursor codes like this one:
input = input.replace(/\x1b\[([0-9]+)C/g, function(_, num) {
return new Array(+num + 1).join(' ');
});
only C, forward just add blanks, it was working for ANSI art but not work with ervy scatter plot.
I think it's not too broad, it's just question about moving cursor and processing newlines using ANSI escape codes. Also it's suppose to be simple case, cursor should move only inside single string not outside like in real terminal (ervy plot output ANSI escape codes like that).
I'm fine with answers that explain how to process the string and how to move the cursor that will work, but if you can provide fixes to the code I would be great. I prefer fixes to my code now whole new implementation unless is much simpler and it's a function parse_ansi_cursor(input) and work the same with rest of the code but with fixed cursor movement.
EDIT:
I've found that my input.split('\n').filter(Boolean) was wrong it should be:
var lines = input.split('\n');
if (input.match(/^\n/)) {
lines.shift();
}
if (input.match(/\n$/)) {
lines.pop();
}
and it seems that some old spec for ANSI escapes say that 0 is not zero but placeholder for default which is 1. That was removed from spec but Xterm is still using this. So I've added this line for parsing code, if there is 0A or A got value 1.
var value = match[1].match(/^0?$/) ? 1 : +match[1];
the plot looks better, but there are still issues with the cursor. (I think it's cursor - I'm not 100% sure).
I've changed the +1/-1 again now it's closer (Almost the same as in XTerm). Buss still there's need to be bug in my code.
EDIT:
afer answer by #jerch I've tried to use node ansi parser, have the same issue don't know how to process the cursor:
var cursor = {x:0,y:0};
result = [];
var terminal = {
inst_p: function(s) {
var line = result[cursor.y];
if (!line) {
result[cursor.y] = s;
} else if (cursor.x === 0) {
result[cursor.y] = s + line.substring(s.length);
} else if (line.length < cursor.x) {
var len = cursor.x - (line.length - 1);
result[cursor.y] += new Array(len).join(' ') + s;
} else if (line.length === cursor.x) {
result[cursor.y] += s;
} else {
var before = line.substring(0, cursor.x);
var after = line.substring(cursor.x + s.length);
result[cursor.y] = before + s + after;
}
cursor.x += s.length;
console.log({s, ...cursor, line: result[cursor.y]});
},
inst_o: function(s) {console.log('osc', s);},
inst_x: function(flag) {
var code = flag.charCodeAt(0);
if (code === 10) {
cursor.y++;
cursor.x = 0;
}
},
inst_c: function(collected, params, flag) {
console.log({collected, params, flag});
var value = params[0] === 0 ? 1 : params[0];
switch(flag) {
case 'A': // UP
cursor.y -= value;
break;
case 'B': // Down
cursor.y += value - 1;
break;
case 'C': // forward
cursor.x += value;
break;
case 'D': // Back
cursor.x -= value;
break;
case 'E': // Cursor Next Line
cursor.x = 0;
cursor.y += value;
break;
case 'F': // Cursor Previous Line
cursor.x = 0;
cursor.y -= value;
break;
}
},
inst_e: function(collected, flag) {console.log('esc', collected, flag);},
inst_H: function(collected, params, flag) {console.log('dcs-Hook', collected, params, flag);},
inst_P: function(dcs) {console.log('dcs-Put', dcs);},
inst_U: function() {console.log('dcs-Unhook');}
};
var parser = new AnsiParser(terminal);
parser.parse(input);
return result.join('\n');
This is just simple example that ignore everything except newline and cursor movement.
Here is the output:
UPDATE:
It seems that every cursor movement should be just += value or -= value and my value - 1; was just correcting to bug in ervy library that was not working on clear terminal.
To begin with - a Regexp based approach is not ideal to handle escape sequences. The reason for this are complicated interactions between various terminal sequences, as some break a former not yet closed one while others keep working in the middle of another (like some control codes) and the "outer" sequence would still finish correctly. You would have to pull in all these edge cases into every single regexp (see https://github.com/xtermjs/xterm.js/issues/2607#issuecomment-562648768 for an illustration).
In general parsing escape sequences is quite tricky, we even have an issue regarding that in terminal-wg. Hopefully we manage to get some minimal parsing requirements from this in the future. Most certainly it will not be regexp-based ;)
All that said, its much easier to go with a real parser, that deals with all the edge cases. A good starting point for a DEC compatible parser is https://vt100.net/emu/dec_ansi_parser. For cursor handling you have to handle at least these states with all actions:
ground
escape
csi_entry
csi_ignore
csi_param
csi_intermediate
plus all other states as dummy entries. Also control codes need special care (action execute), as they might interfer anytime with any other sequence with different results.
To make things even worse, the official ECMA-48 specifiction slightly differs for certain aspects from the DEC parser. Still most emulators used these days try to aim for DEC VT100+ compatibility.
If you dont want to write the parser yourself, you can either use/modify my old parser or the one we have in xterm.js (the latter might be harder to integrate as it operates on UTF32 codepoints).
I'm relatively new to coding and working on a text based RPG game in JavaScript. The following code allows me to progress through the different scenarios where you are approached with a different bad guy.
I used a For loop in conjunction with a Switch statement and had it working prior, but then I re factored my code to make it more OO & prototypal. Now my For loop continues looping and does not exit. I checked the value of [i] throughout and see it properly goes 0-4, but then it restarts at 0 and I can't figure out why?
var scenario = new Array();
//simple function to create the number of scenarios
function Scenario () {
howManyScenarios = function(number) {
for (i=0; i <= number; i++) {
scenario[i] = ("Scenario " + (1 + i));
};
};
howManyScenarios(4); //if you change the argument, add additional switch cases
//iterating through my howManyScenarios function to build out scenarios using a switch case
createScenarios = function () {
var ii = scenario.length;
for (i=0; i < ii; i++) {
switch(scenario[i]) {
case 'Scenario 1':
alert("You run into a troll");
b = 0;
break;
case 'Scenario 2':
alert("You find a store to purchase goods from");
ItemShop();
break;
case 'Scenario 3':
alert("You run into a ogre");
b = 1;
break;
case 'Scenario 4':
alert("You run into a warewolf");
b = 2;
break;
case 'Scenario 5':
alert("You run into a wizard");
b = 3;
return;
break;
}; //close out switch cases
}; //close out my for loop
}; //close out createScenarios function
createScenarios();
}; //close out Scenario function
Scenario();
Your loop will obviously still continue because you just only ended a case of every loop of i and will still test each value in the array of scenario[i].
How about using variable b as a handler that if an event like you run into a troll has been executed, then set b to a number greater than 0 then check if a value has been inserted into b before switching into the array again using if (b) break; where if b has a value greater than 0 then it will be set as true.
var scenario = new Array();
var b;
//simple function to create the number of scenarios
function Scenario() {
howManyScenarios = function (number) {
for (i = 0; i <= number; i++) {
scenario[i] = ("Scenario " + (1 + i));
};
};
howManyScenarios(4); //if you change the argument, add additional switch cases
console.log(scenario[i]);
//iterating through my howManyScenarios function to build out scenarios using a switch case
createScenarios = function () {
var ii = scenario.length;
for (i = 0; i < ii; i++) {
if (b) break;
switch (scenario[i]) {
case 'Scenario 1':
alert("You run into a troll");
b = 1;
break;
case 'Scenario 2':
alert("You find a store to purchase goods from");
b = 2;
ItemShop();
break;
case 'Scenario 3':
alert("You run into a ogre");
b = 3;
break;
case 'Scenario 4':
alert("You run into a warewolf");
b = 4;
break;
case 'Scenario 5':
alert("You run into a wizard");
b = 5;
return;
break;
}; //close out switch cases
}; //close out my for loop
}; //close out createScenarios function
createScenarios();
}; //close out Scenario function
Scenario();
function ItemShop() {}
ANSWER 2
This one is one way on how we game developers make a functional game by using a series of object arrays, object classes and the like.
I remade your code into something easier to read, hope you learn something from this. :)
var numberofscenarios = 5;
var scenario = []; //array where scenarios will be
//this will be the accessible properties of scenario[] array
var _scenario = function(){
this.name = ""; //name of scenario
this.message = "";
this.doSomething = 0;
this.status = 0 ;//1 = finished and 0 = false
};
var _event = function(mobname){
this.mobname = mobname;
this.battle = function(){//doSomething
console.log("Battle VS "+ this.mobname +" Start!");
};
this.itemShop = function(){//doSomething
console.log(this.mobname + ": Welcome to the shop! How may I help you?");
};
};
//generate the scenarios in the scenario[] array
function generateScenarios() {
for (i = 0; i <= numberofscenarios; i++) {
scenario[i] = new _scenario();
scenario[i].name = i;
switch (scenario[i].name) {
case 1:
scenario[i].message = "You run into a Troll";
scenario[i].doSomething = new _event("Troll");
break;
case 2:
scenario[i].message = "You find a store to purchase goods from";
scenario[i].doSomething = new _event("Shop Keeper");
break;
case 3:
scenario[i].message = "You run into a Ogre";
scenario[i].doSomething = new _event("Ogre");
break;
case 4:
scenario[i].message = "You run into a Werewolf";
scenario[i].doSomething = new _event("Werewolf");
break;
case 5:
scenario[i].message = "You run into a Wizard";
scenario[i].doSomething = new _event("Wizard");
break;
}
}
}
generateScenarios(); //generate the scenarios
//test the array of scenario class
//test the battle with Troll
console.log(scenario[1].message);
scenario[1].doSomething.battle();
//test the shop
console.log(scenario[2].message);
scenario[2].doSomething.itemShop();
//attempt to fight the Shopkeeper
console.log(scenario[2].message);
scenario[2].doSomething.battle();