Skip to content
Snippets Groups Projects
Commit 0f3a17ba authored by cvs2git's avatar cvs2git
Browse files

This commit was manufactured by cvs2svn to create tag 'release-1'.

parent 823498e9
No related branches found
No related tags found
No related merge requests found
************************************
***** BBS DICE WARZ (2008) ******
** for use with Synchronet v3.14+ **
*** by Matt Johnson **************
************************************
This game was modelled after "Dice Wars" which is a web-interface strategy
game involving dice, similar to Risk.
The object of the game is to conquer the map by rolling dice against
neighboring tiles. The game can be played by 4 to 7 players, and can
be either 1 human player vs. all computer players, all human vs. human
players, or a mix of humans and computers.
While the settings can be adjusted, the default maximum dice per tile is 8,
and the default maximum reserve dice is 30.
####GAMEPLAY####
When it is your turn, you press "T" to start your turn, and then "A" to
begin attacking. Use the arrow keys to move around the map, and the [ENTER]
key to select a territory. It would make sense to not attack a tile when
the odds are against you. You are not required to make an attack at all,
and you can simply press "E" to end your turn immediately if you only wish
to place reinforcements.
Example:
Attacking tile's dice: 2 (6 + 6)
Defending tile's dice: 8 (6 + 6 + 6 + 6 + 6 + 6 + 6 + 6)
In this scenario, the highest possible roll you can get as the attacker is
a 12, whereas the highest roll the defender can get is 48. You will most
likely lose, and would be better off attacking somewhere else.
When rolling dice against another player, all ties go to the defender.
If you win the dice roll, the defending tile becomes yours, and all but
one of your dice are automatically moved to the tile. The remaining die
is left behind on the tile from which you attacked.
When you are finished attacking press "E" to end your turn, and you will
be given reinforcement dice equal to the largest number of CONNECTED
tiles you possess. This creates a secondary objective in the game which
is to connect as many of your tiles on board as possible, so as to get
more reinforcements. These are placed randomly on your tiles.
If all of your tiles have reached the maximum number of dice per tile,
any remaining reinforcements will be added to a reserve, up to a maximum
of 30 dice. These reserve dice will be placed at the end of your turn
along with your regular reinforcements as needed, unless all of your
territories are already full.
The game is over (for you) when you have either conquered all of the
tiles on the board, or had all of your tiles taken over by other players.
####SCORING####
1st place: +2 points
2nd place: +1 point
3rd place: no change
4th place: -1 point
5th place: -2 points
6th place: -2 points
7th place: -2 points
####THANKS TO####
Landis for his coding advice.
Chrispi for his relentless bug detection.
Now everyone go get killed!
/* **********************************
****** DICE WARZ (2008) ******
** for use with Synchronet v3.14+ **
*** by Matt Johnson *************
**********************************
SET TAB STOPS TO 4 FOR EDITING
SEARCH "TODO:" ENTRIES FOR
CODE THAT NEEDS WORK
*/
load("sbbsdefs.js");
load("graphic.js");
var game_dir;
try { barfitty.barf(barf); } catch(e) { game_dir = e.fileName; }
game_dir = game_dir.replace(/[^\/\\]*$/,'');
load(game_dir + "diceroll.js");
load(game_dir + "lock.js");
load(game_dir + "maps.js");
load(game_dir + "territory.js");
load(game_dir + "menu.js");
load(game_dir + "player.js");
load(game_dir + "display.js");
var activeGame="";
//######################### InitIALIZE PROGRAM VARIABLES #########################
const pointsToWin= 100;
const maxGames= 100;
const minPlayers= 3;
const maxPlayers= 7;
const maxDice= 8;
const root= "GAME";
const scorefile= "DICERANK";
const instructions= "DICE.DOC";
const bColors= [BG_BLUE, BG_CYAN, BG_RED, BG_GREEN, BG_BROWN, BG_MAGENTA, BG_LIGHTGRAY]; //MAP BACKGROUND COLORS
const bfColors= [BLUE, CYAN, RED, GREEN, BROWN, MAGENTA, LIGHTGRAY]; //MAP BACKGROUND COLORS (FOREGROUND CHARS)
const fColors= ["\1h\1w", "\1h\1c", "\1h\1r", "\1h\1g", "\1h\1y", "\1h\1m", "\1k"]; //MAP FOREGROUND COLORS
const border_color= "\1n\1k\1h";
//######################### DO NOT CHANGE THIS SECTION ##########################
var log_list=[];
if(!file_isdir(game_dir+"logs")) mkdir(game_dir+"logs");
else log_list=directory(game_dir + "logs/*.log");
var logfile=new File(game_dir + "logs/dice" + log_list.length + ".log");
logfile.open('w+',false);
logfile.writeln("######DICE WARZ LOG DATA####### " + system.datestr() +" - "+ system.timestr());
//TODO: MAKE BETTER USER OF THE USER FILES. CAN BE USED FOR REALTIME MULTIPLAYER, AND FOR USER PRESENCE DETECTION
// IN THE EVENT A USER IS BEING NOTIFIED OF HIS OR HER TURN IN A GAME, THE TELEGRAMS WILL BE SUPPRESSED IF THE USER IS ALREADY RUNNING THE PROGRAM
var userFileName=game_dir + user.alias + ".USR";
var userFile=new File(userFileName);
userFile.open('a');
userFile.close();
//TODO: MAKE REALTIME MULTIPLAYER FEATURES POSSIBLY USING THE EXISTING FILE LOCK SYSTEM OR QUEUES
// var dataQueue= new Queue(dice);
const daySeconds= 86400;
const startRow= 4;
const startColumn= 3;
const menuRow= 1;
const menuColumn= 50;
const columns= 9;
const rows= 9;
const blackBG= console.ansi(ANSI_NORMAL);
//TODO: FIX SCORING SYSTEM... BECAUSE RIGHT NOW IT SUCKS
const points= [-2,-2,-2,-1,0,1,2]; //POINTS GAINED/LOST FOR WINNING/LOSING
var scores= [];
var messages= []; //MESSAGES QUEUED FOR DISPLAY UPON RELOADING MAIN MENU
var games= new GameStatusInfo();
var dice= LoadDice();
var oldpass= console.ctrlkey_passthru;
console.ctrlkey_passthru="+ACGKLOPQRTUVWXYZ_";
bbs.sys_status|=SS_MOFF;
SplashScreen();
GameMenu();
//########################## MAIN FUNCTIONS ###################################
function ScanProximity(location)
{
var prox=[];
var odd=false;
offset=location%columns;
if((offset%2)==1) odd=true;
if(location>=columns) //if not in the first row
prox[0]=(location-columns); //north
if(location<(columns*(rows-1))) //if not in the last row
prox[1]=(location+columns); //south
if(odd)
{
if(((location+1)%columns)!=1) //if not in the first column
prox[2]=location-1; //northwest
if(((location+1)%columns)!=0) //if not in the last column
prox[3]=location+1; //northeast
if(location<(columns*(rows-1))) //if not in the last row
{
if(((location+1)%columns)!=1) //if not in the first column
prox[4]=prox[1]-1; //southwest
if(((location+1)%columns)!=0) //if not in the last column
prox[5]=prox[1]+1; //southeast
}
}
else
{
if(location>=columns) //if not in the first row
{
if(((location+1)%columns)!=1) //if not in the first column
prox[2]=prox[0]-1; //northwest
if(((location+1)%columns)!=0) //if not in the last column
prox[3]=prox[0]+1; //northeast
}
if(((location+1)%columns)!=1) //if not in the first column
prox[4]=location-1; //southwest
if(((location+1)%columns)!=0) //if not in the last column
prox[5]=location+1; //southeast
}
return prox;
}
function GetNextGameNumber()
{
var next=1;
while(games.gameData[next]) {
next++;
}
return next;
}
function CountSparseArray(data)
{
var count=0;
for(tt in data)
{
count++;
}
if(count==0) return false;
else return count;
}
function ViewInstructions()
{
console.clear();
console.printfile(game_dir + instructions);
if(!(user.settings & USER_PAUSE)) console.pause();
console.aborted=false;
}
function ViewRankings()
{
scores=games.LoadRankings();
var scoredata=SortScores();
console.clear();
printf("\1k\1h\xDA");
printf(PrintPadded("\xC2",31,"\xC4","right"));
printf(PrintPadded("\xC2",9,"\xC4","right"));
printf(PrintPadded("\xC2",12,"\xC4","right"));
printf(PrintPadded("\xC2",14,"\xC4","right"));
printf(PrintPadded("\xBF",13,"\xC4","right"));
printf("\1k\1h\xB3\1n\1g DICE WARZ RANKINGS \1k\1h\xB3 \1n\1gPOINTS \1k\1h\xB3 \1n\1gSOLO WINS \1k\1h\xB3 \1n\1gSOLO LOSSES \1k\1h\xB3 \1n\1gSOLO WIN % \1k\1h\xB3");
printf("\xC3");
printf(PrintPadded("\xC5",31,"\xC4","right"));
printf(PrintPadded("\xC5",9,"\xC4","right"));
printf(PrintPadded("\xC5",12,"\xC4","right"));
printf(PrintPadded("\xC5",14,"\xC4","right"));
printf(PrintPadded("\xB4",13,"\xC4","right"));
for(hs in scoredata)
{
thisuser=scoredata[hs];
if(scores[thisuser].score>0 || scores[thisuser].wins>0)
{
var winPercentage=0;
if(scores[thisuser].wins>0) winPercentage=(scores[thisuser].wins/(scores[thisuser].wins+scores[thisuser].losses))*100;
printf("\1k\1h\xB3");
printf(PrintPadded("\1y\1h " + system.username(thisuser),30," ","left"));
printf("\1k\1h\xB3");
printf(PrintPadded("\1w\1h" + scores[thisuser].score + " \1k\1h\xB3",9," ","right"));
printf(PrintPadded("\1w\1h" + scores[thisuser].wins + " \1k\1h\xB3",12," ","right"));
printf(PrintPadded("\1w\1h" + scores[thisuser].losses + " \1k\1h\xB3",14," ","right"));
printf(PrintPadded("\1w\1h" + winPercentage.toFixed(2) + " % \1k\1h\xB3",13," ","right"));
}
}
printf("\1k\1h\xC0");
printf(PrintPadded("\xC1",31,"\xC4","right"));
printf(PrintPadded("\xC1",9,"\xC4","right"));
printf(PrintPadded("\xC1",12,"\xC4","right"));
printf(PrintPadded("\xC1",14,"\xC4","right"));
printf(PrintPadded("\xD9",13,"\xC4","right"));
console.gotoxy(1,24);
console.pause();
console.aborted=false;
}
function Sort(iiii)
{
var Sorted=[];
for(cc in iiii)
{
Sorted.push(cc);
}
Sorted.sort();
return Sorted;
}
function AttackMessage(txt)
{
var x=menuColumn;
ClearArea(16,menuColumn,8);
console.gotoxy(x,16);
console.putmsg("\1r\1h Choose a territory");
console.gotoxy(x,17);
console.putmsg("\1r\1h " + txt);
console.gotoxy(x,18);
console.putmsg("\1r\1h or 'Q' to cancel.");
console.gotoxy(x,20);
console.putmsg("\1r\1h Use the arrow keys");
console.gotoxy(x,21);
console.putmsg("\1r\1h to move, and \1n\1r[\1hENTER\1n\1r]");
console.gotoxy(x,22);
console.putmsg("\1r\1h to select a tile.");
WipeCursor("left");
}
/*
//TODO: IMPROVE SCORING METHODS
SCORES ARE STORED IN A SPARSE ARRAY. COMPRESS THE INDICES OF THE SCORES INTO A SEQUENTIAL LIST
THEN SORT THE LIST HIGHEST SCORE TO LOWEST SCORE AND RETURN A NEW ARRAY OF POINTERS TO SCORE INDICES
I'M SURE THERE'S A BETTER WAY, IT JUST HASN'T OCCURRED TO ME YET
*/
function CompressScores()
{
compressed=[];
for(score in scores)
{
compressed.push(score);
}
return compressed;
}
function SortScores()
{
var data=CompressScores();
var numScores=data.length;
for(n=0;n<numScores;n++)
{
for(m = 0; m < (numScores-1); m++)
{
if(scores[data[m]].score < scores[data[m+1]].score)
{
holder = data[m+1];
data[m+1] = data[m];
data[m] = holder;
}
}
}
return data;
}
function DeliverMessage(nextTurnPlayer,gameNumber)
{
var nextUserName=system.username(nextTurnPlayer);
var message="\1r\1hIt is your turn in \1yDice-Warz\1r game #" + gameNumber + "\r\n\r\n";
var nextUserFileName=game_dir + nextUserName + ".USR";
if(file_exists(nextUserFileName)) {
var nextUserFile=new File(nextUserFileName);
nextUserFile.open('a',true);
nextUserFile.writeln(message);
nextUserFile.close();
}
else system.put_telegram(nextTurnPlayer, message);
}
//########################GAME MENU FUNCTIONS################################
function SplashScreen()
{
console.clear();
var splash_filename=game_dir + "DICEWARZ.BIN";
var splash_size=file_size(splash_filename);
splash_size/=2; // Divide by two for attr/char pairs
splash_size/=80; // Divide by 80 cols. Size should now be height (assuming int)
var Splash=new Graphic(80,splash_size);
Splash.load(splash_filename);
Splash.draw();
console.gotoxy(1,23);
console.center("\1n\1c[\1hPress any key to continue\1n\1c]");
while(console.inkey(K_NOECHO|K_NOSPIN)=="");
}
function GameMenu()
{
if(!(user.settings & USER_PAUSE)) console.pause();
var gMenu=new Menu( "" ,1,19,GetColor("green"),GetColor("green","high"));
var gmenu_items=[ "~Rankings" ,
"~Select Game" ,
"~Begin New Game" ,
"~Instructions" ,
"~Quit to BBS" ];
gMenu.add(gmenu_items);
games.Init();
while(1)
{
//LOOPING MAIN MENU, UPDATES GAME STATUS INFO UPON REFRESH
//TODO: make recently completed games disappear from "your turn" list upon refresh
games.UpdateGames();
console.clear();
console.putmsg("\1r\1hB B S - D I C E - W A R Z ! \1n\1c- Matt Johnson - 2008");
console.crlf();
DrawLine("\1n\1w\1h",79);
console.crlf();
console.gotoxy(1,18);
DrawLine("\1n\1w\1h",79);
console.gotoxy(1,24);
DrawLine("\1n\1w\1h",79);
gMenu.display();
console.gotoxy(1,3);
Wrap("\1g Games in progress ",games.inProgress);
Wrap("\1g Games needing more players ",games.notFull);
Wrap("\1g Completed Games ",games.completed);
Wrap("\1g You are involved in games ",games.yourGames);
Wrap("\1g It is your turn in games ",games.yourTurn);
Wrap("\1g You are eliminated in games",games.eliminated);
Wrap("\1g You have won games ",games.youWin);
Wrap("\1g Single-player games ",games.singleGames);
DisplayMessages();
WipeCursor("right");
var cmd=console.getkey(K_NOSPIN|K_NOECHO|K_NOCRLF|K_UPPER);
switch(cmd)
{
case "R":
ViewRankings();
break;
case "S":
var choice=ChooseGame();
if(choice) ProcessSelection(choice);
break;
case "I":
ViewInstructions();
break;
case "B":
CreateNewGame();
break;
case "Q":
Quit(0);
break;
default:
break;
}
WipeCursor("right");
}
}
function ChooseGame()
{
x=30; y=19
while(1)
{
console.gotoxy(x,y);
console.cleartoeol();
if(!games.gameData.length)
{
PutMessage("\1r\1hThere are currently no games.",x,y);
break;
}
console.putmsg("\1n\1gEnter game number or [\1hQ\1n\1g]uit\1h: ");
game_num=console.getkeys("Q",maxGames);
if(game_num=="Q") return false;
if(games.gameData[game_num])
{
var game_data=games.gameData[game_num];
var num=game_num;
if(game_num<10) num="0" + num;
gamefile=root + num;
if(Locked(gamefile))
PutMessage("\1r\1hThat game is in use by another node.",x,y);
else
{
if(game_data.singlePlayer)
{
if(games.gameData[game_num].users[user.number]>0);
else
{
PutMessage("\1r\1hGame #" + game_num + " is private.",x,y);
continue;
}
}
return game_num;
}
}
else PutMessage("\1r\1hNo Such Game!",x,y);
}
return false;
}
function ProcessSelection(gameNumber)
{
var num=gameNumber;
if(gameNumber<10) num="0" + num;
var gamefile=root + num;
Lock(gamefile);
var g=games.gameData[gameNumber];
var fileName=g.fileName;
var lastModified=file_date(fileName);
if(lastModified>g.lastModified) games.gameData[gameNumber]=LoadGame(fileName,gameNumber,lastModified);
if(g.status>=0)
{
GameLog("Loading game: " + gameNumber);
PlayGame(gameNumber);
}
else
{
GameLog("Viewing game info: " + gameNumber);
ViewGameInfo(gameNumber);
if(g.users[user.number]>=0)
{
var gamePlayer=g.users[user.number];
if(g.fixedPlayers) AskRemove(gameNumber,gamePlayer);
else ChangeVote(gameNumber,user.number);
}
else JoinGame(gameNumber);
}
Unlock(gamefile);
ClearArea(19,30,4);
}
function ChangeVote(gameNumber,userNumber)
{
console.gotoxy(30,19);
console.cleartoeol();
var g=games.gameData[gameNumber];
var gamePlayer=g.users[userNumber];
if(console.noyes("\1n\1gChange your vote?"))
{
console.gotoxy(30,20);
console.cleartoeol();
AskRemove(gameNumber,gamePlayer);
}
else
{
var vote=g.players[gamePlayer].vote;
if(vote==1) g.players[gamePlayer].vote=0;
else g.players[gamePlayer].vote=1;
if(g.tallyVotes())
{
g.maxPlayers=g.countPlayers();
StartGame(gameNumber);
}
games.StoreGame(gameNumber);
}
}
function AskRemove(gameNumber,playerNumber)
{
g=games.gameData[gameNumber];
if(console.noyes("\1n\1gRemove yourself from this game?"));
else
{
g.removePlayer(playerNumber);
if(g.countHumanPlayers()==0)
{
file_remove(g.fileName);
}
else games.StoreGame(gameNumber);
}
}
function ViewGameInfo(gameNumber)
{
g=games.gameData[gameNumber];
ClearArea(3,1,14)
console.gotoxy(2,4);
console.putmsg("\1g[ \1hGAME: #" + gameNumber + " \1n\1g]\r\n");
if(g.maxPlayers>g.minPlayers)
console.putmsg("\1n\1g Minimum Players: \1h" + g.minPlayers + " \1n\1gMaximum: \1h" + g.maxPlayers + "\r\n");
else
console.putmsg("\1n\1g Players Needed to Start: \1h" + g.maxPlayers + "\r\n");
console.putmsg("\1n\1g Players In This Game:\r\n");
for(playerNumber=0;playerNumber<g.players.length;playerNumber++)
{
player=g.players[playerNumber];
console.putmsg("\1g\1h " + GetUserName(player,playerNumber));
if(player.vote>=0) {
if(player.vote==0) vote="wait";
else vote="start";
if(g.maxPlayers>g.minPlayers)
console.putmsg(" \1n\1gvotes to \1h" + vote);
}
console.crlf();
}
console.crlf();
}
function StartGame(gameNumber)
{
g=games.gameData[gameNumber];
var maxPlayers=g.maxPlayers;
var players=g.players;
games.gameData[gameNumber]=new Map(columns,rows,maxPlayers,gameNumber);
games.gameData[gameNumber].players=players;
games.inProgress.push(gameNumber);
games.gameData[gameNumber].Init();
games.gameData[gameNumber].singlePlayer=g.singlePlayer;
games.gameData[gameNumber].fileName=g.fileName;
games.gameData[gameNumber].lastModified=time();
QueueMessage("\1r\1hGame " + gameNumber + " Initialized!",30,20);
games.gameData[gameNumber].Notify();
games.StoreGame(gameNumber);
}
function JoinGame(gameNumber)
{
g=games.gameData[gameNumber];
if(console.noyes("\1n\1gJoin this game?"));
else
{
vote=GetVote();
g.addPlayer(user.number,vote);
if(g.players.length>=g.minPlayers)
{
if(g.players.length==g.maxPlayers ||
g.tallyVotes())
{
g.maxPlayers=g.players.length;
StartGame(gameNumber);
}
}
else games.StoreGame(gameNumber);
}
}
function CreateNewGame()
{
var minNumPlayers=-1;
var maxNumPlayers=7;
var numComputerPlayers=-1;
var singlePlayer=false;
var fixedPlayers=false;
var vote=-1;
var x=30; var y=19
console.gotoxy(x,y);
console.cleartoeol();
if(console.yesno("\1n\1gBegin a new game?"))
{
ClearArea(3,1,14);
ClearArea(19,30,5);
var gameNumber=GetNextGameNumber();
var gnum=gameNumber;
GameLog("creating new game: " + gnum);
if(gameNumber<10) gnum="0" + gnum;
var gamefile=root + gnum;
Lock(gamefile);
}
else
{
console.gotoxy(x,y);
console.cleartoeol();
return false;
}
while(1)
{
x=2; y=4;
console.gotoxy(x,y);
console.cleartoeol();
console.putmsg("\1n\1gEnter minimum number of players [\1h" + minPlayers + "\1n\1g-\1h" + maxPlayers + "\1n\1g] or [\1hQ\1n\1g]uit: ");
var num=console.getkeys("Q",maxPlayers);
if(num>=minPlayers && num<=maxPlayers)
{
minNumPlayers=num;
break;
}
else if(num=="Q") return false;
else PutMessage("\1r\1h Please enter a number within the given range.",x,y);
}
if(minNumPlayers<maxPlayers) {
while(1)
{
x=2; y=5;
console.gotoxy(x,y);
console.cleartoeol();
console.putmsg("\1n\1gEnter maximum number of players [\1h" + minNumPlayers + "\1n\1g-\1h" + maxPlayers + "\1n\1g] or [\1hQ\1n\1g]uit: ");
var num=console.getkeys("Q",maxPlayers);
if(num>=minNumPlayers && num<=maxPlayers)
{
maxNumPlayers=num;
break;
}
else if(num=="Q") return false;
else PutMessage("\1r\1h Please enter a number within the given range.",x,y);
}
}
if(minNumPlayers==maxNumPlayers) fixedPlayers=true;
while(1)
{
x=2; y=6;
console.gotoxy(x,y);
console.cleartoeol();
if(console.noyes("\1n\1gInclude computer players?")) break;
console.gotoxy(x,y);
console.cleartoeol();
console.putmsg("\1n\1gHow many? [\1h1\1n\1g-\1h" + (maxNumPlayers-1) + "\1n\1g] or [\1hQ\1n\1g]uit: ");
cnum=console.getkeys("Q",maxNumPlayers-1);
if(cnum<=(maxNumPlayers-1) && cnum>0)
{
numComputerPlayers=cnum;
break;
}
else if(cnum=="Q") return false;
else PutMessage("\1r\1h Please enter a number within the given range.",x,y);
}
games.gameData[gameNumber]=new NewGame(minNumPlayers,maxNumPlayers,gameNumber);
games.gameData[gameNumber].fileName=GetFileName(gameNumber);
for(cp=0;cp<numComputerPlayers;cp++)
{
games.gameData[gameNumber].addPlayer(-1, -1); //NO USER NUMBER, NO VOTE
}
if(numComputerPlayers+1==maxNumPlayers) {
singlePlayer=true;
GameLog("single player game");
}
else {
if(fixedPlayers) games.gameData[gameNumber].fixedPlayers=true;
else
{
console.crlf();
vote=GetVote();
}
}
games.gameData[gameNumber].addPlayer(user.number, vote);
if(singlePlayer)
{
games.gameData[gameNumber].singlePlayer=true;
StartGame(gameNumber);
games.singleGames.push(gameNumber);
games.yourGames.push(gameNumber);
games.yourTurn.push(gameNumber);
}
else games.notFull.push(gameNumber);
games.StoreGame(gameNumber);
QueueMessage("\1r\1hGame " + gameNumber + " Created!",30,20);
Unlock(gamefile);
return true;
}
function GetFileName(gameNumber)
{
var num=gameNumber;
if(gameNumber<10) num="0" + gameNumber;
var gamefile=root + num;
return (game_dir + gamefile + ".DAT");
}
function GetVote()
{
var vote=0;
console.putmsg("\1n\1gDo you wish to start the game immediately or wait for more players?");
console.crlf();
if(console.yesno("\1g\1hYes to start, No to wait"))
{
vote = 1;
}
GameLog("got user vote: " + vote);
return vote;
}
function GetUserName(playerData,playerNumber)
{
if(playerData.user>=0) UserName=system.username(playerData.user);
else UserName="Computer " + (playerNumber+1);
return UserName;
}
//###########################GAMEPLAY FUNCTIONS#############################
function SelectTile(gameNumber,playerNumber,attackPosition,startPosition)
{
var g=games.gameData[gameNumber];
if(attackPosition>=0)
{
terr=g.grid[attackPosition]; //IF A BOARD POSITION HAS BEEN SUPPLIED TO ATTACK FROM, START THERE
GameLog("attacking position supplied: " + attackPosition);
}
else if(startPosition>=0)
{
terr=g.grid[startPosition]; //IF A BOARD POSITION HAS BEEN SUPPLIED TO START FROM, START THERE
ShowSelected(terr,"\1n\1w\1h");
GameLog("starting position supplied: " + startPosition);
}
else //OTHERWISE, START WITH THE FIRST PLAYER TERRITORY THAT IS CAPABLE OF ATTACKING
{
GameLog("no starting position supplied");
var p=g.players[playerNumber];
for(tile in p.territories)
{
terr=g.grid[p.territories[tile]];
if(terr.dice>1)
{
ShowSelected(terr,"\1n\1w\1h");
break;
}
}
}
dir=terr.location;
while(1)
{
var key=console.getkey((K_NOECHO,K_NOCRLF,K_UPPER));
if(key=="\r" || key==undefined)
{
if(attackPosition>=0)
{
if(terr.player==playerNumber);
else
{
if(terr.location==g.grid[attackPosition].North) return terr;
if(terr.location==g.grid[attackPosition].South) return terr;
if(terr.location==g.grid[attackPosition].Northeast) return terr;
if(terr.location==g.grid[attackPosition].Northwest) return terr;
if(terr.location==g.grid[attackPosition].Southeast) return terr;
if(terr.location==g.grid[attackPosition].Southwest) return terr;
}
}
else if(terr.player==playerNumber && terr.dice>1) return terr;
}
switch(key)
{
case KEY_DOWN:
case '2':
if(g.grid[terr.South])
dir=terr.South
break;
case KEY_UP:
case '5':
if(g.grid[terr.North])
dir=terr.North;
break;
case '1':
if(g.grid[terr.Southwest])
dir=terr.Southwest;
break;
case '4':
if(g.grid[terr.Northwest])
dir=terr.Northwest;
break;
case '3':
if(g.grid[terr.Southeast])
dir=terr.Southeast;
break;
case '6':
if(g.grid[terr.Northeast])
dir=terr.Northeast;
break;
case KEY_LEFT:
if(g.grid[terr.Southwest])
dir=terr.Southwest;
else if(g.grid[terr.Northwest])
dir=terr.Northwest;
break;
case KEY_RIGHT:
if(g.grid[terr.Northeast])
dir=terr.Northeast;
else if(g.grid[terr.Southeast])
dir=terr.Southeast;
break;
case "Q":
terr.displayBorder(border_color);
return false;
default:
continue;
}
terr.displayBorder(border_color);
terr=g.grid[dir];
ShowSelected(terr,"\1n\1w\1h");
}
WipeCursor("left");
}
function ShowSelected(selection,color)
{
selection.displaySelected(color);
WipeCursor("left");
}
function Attack(gameNumber,playerNumber)
{
ClearArea(16,menuColumn,8);
AttackMessage("from which to Attack,");
var attackFrom=SelectTile(gameNumber,playerNumber,-1,games.gameData[gameNumber].lastMapPosition);
if(attackFrom==false) return false;
ClearArea(16,menuColumn,8);
AttackMessage("to Attack,");
var attackTo=SelectTile(gameNumber,playerNumber,attackFrom.location);
if(attackTo==false) return false;
var tofrom=Battle(attackFrom,attackTo,gameNumber);
if(tofrom=true) games.gameData[gameNumber].lastMapPosition=attackTo.location;
else games.gameData[gameNumber].lastMapPosition=attackFrom.location;
return true;
}
function Battle(attackFrom,attackTo,gameNumber)
{
var g=games.gameData[gameNumber];
ClearArea(16,menuColumn,8);
ShowSelected(attackFrom,"\1n\1r\1h");
ShowSelected(attackTo,"\1n\1r\1h");
var totals=RollDice(attackFrom.dice,attackTo.dice);
GameLog("attackingfrom: " + attackFrom.dice + " attackingTo: " + attackTo.dice);
var defender=attackTo.player;
var attacker=attackFrom.player;
var defending=attackTo.location;
var attacking=attackFrom.location;
if(totals[0]>totals[1])
{
GameLog("transferring ownership of tiles");
g.players[defender].removeTerritory(defending); //REMOVE TILE FROM DEFENDER'S LIST
g.players[attacker].territories.push(defending); //ADD TILE TO ATTACKER'S LIST
g.players[defender].totalDice-=(attackTo.dice);
g.grid[defending].assign(attacker,g.players[attacker]);
g.grid[defending].dice=(attackFrom.dice-1);
if(g.players[defender].territories.length==0)
{
g.EliminatePlayer(defender,g.players[attacker].user);
if(g.CheckElimination()) games.StoreGame(gameNumber);
}
}
g.grid[attacking].dice=1;
attackFrom.show();
attackFrom.displayBorder(border_color);
attackTo.displayBorder(border_color);
attackTo.show();
}
function EndTurn(gameNumber,pl)
{
GameLog("###ENDING TURN");
var g=games.gameData[gameNumber];
var placed=g.Reinforce(pl);
ClearArea(16,menuColumn,9);
console.gotoxy(menuColumn,16);
console.putmsg("\1r\1hPlaced " + placed.length + " reinforcements");
mswait(500);
ClearArea(16,menuColumn,9);
for(place in placed) g.grid[placed[place]].show();
g.takingTurn=false;
games.StoreGame(gameNumber);
}
//MAIN GAMEPLAY FUNCTION
function PlayGame(gameNumber)
{
console.clear();
var g=games.gameData[gameNumber];
var userInGame;
var currentPlayer;
g.Redraw();
var pMenu=new Menu( "" ,1,1,GetColor("green"),GetColor("green","high"));
var pmenu_items=[ "~Take Turn" ,
"~Attack" ,
"~End Turn" ,
"~Redraw" ,
"~Quit" ];
pMenu.add(pmenu_items);
pMenu.disable("A");
pMenu.disable("E");
pMenu.disable("T");
if(g.users[user.number]>=0)
{
userInGame=true;
currentPlayer=g.users[user.number];
}
else
{
currentPlayer=-1;
userInGame=false;
}
ClearArea(16,menuColumn,9);
while(1)
{
if(g.status==0)
{
pMenu.disable("A");
pMenu.disable("E");
pMenu.disable("T");
pMenu.enable("Q");
ShowWinner(g);
}
else
{
var turn=g.turnOrder[g.nextTurn];
var humans=g.CountActiveHumans();
while(g.players[turn].user<0 && userInGame && g.status==1 && humans>=1)
{
ClearArea(16,menuColumn,8);
////////////////////////////////////
GameLog("####COMPUTER PLAYER TAKING TURN");
ClearLine(1,48);
console.gotoxy(2,1);
console.putmsg("\1r\1hPlease wait. Computer player " + (turn+1) + " taking turn.");
mswait(750);
/////////////////////////////////////
while(g.CanAttack(turn))
{
if(TakeTurnAI(gameNumber,turn));
else break;
}
g.takingTurn=true;
EndTurn(gameNumber,turn);
humans=g.CountActiveHumans();
g.DisplayPlayers();
turn=g.turnOrder[g.nextTurn];
}
if(!g.takingTurn)
{
if(turn==currentPlayer)
{
pMenu.enable("T");
GameLog("it is the current user's turn");
}
else if(g.status==0)
{
pMenu.disable("A");
pMenu.disable("E");
pMenu.disable("T");
pMenu.enable("Q");
ShowWinner(g);
}
else
{
ClearArea(16,50,8);
console.gotoxy(51,16);
console.putmsg("\1r\1hIt is " + GetUserName(g.players[turn],turn) + "'s turn");
var daysOld=g.FindDaysOld();
var hoursOld=parseInt(daysOld*24);
if(daysOld>0)
{
console.gotoxy(51,17);
console.putmsg("\1r\1hLast turn taken " + hoursOld + " hours ago");
}
}
}
}
pMenu.displayHorizontal();
var cmd=console.getkey((K_NOECHO,K_NOCRLF,K_UPPER));
WipeCursor("right");
if(pMenu.disabled[cmd]);
else
{
switch(cmd)
{
case "T":
pMenu.disable("T");
pMenu.disable("Q");
g.takingTurn=true;
GameLog("######TAKING TURN");
if(g.CanAttack(currentPlayer,-1))
{
pMenu.enable("A");
}
pMenu.enable("E");
continue;
case "A":
if(Attack(gameNumber,currentPlayer));
else
{
GameLog("player cancelled attack");
continue;
}
g.DisplayPlayers();
break;
case "E":
pMenu.disable("A");
pMenu.disable("E");
pMenu.enable("Q");
g.takingTurn=false;
EndTurn(gameNumber,currentPlayer);
g.DisplayPlayers();
break;
case "R":
console.clear();
g.Redraw();
continue;
case "Q":
return;
break;
default:
WipeCursor("left");
continue;
}
}
}
}
function TakeTurnAI(gameNumber,playerNumber)
{
g=games.gameData[gameNumber];
computerPlayer=g.players[playerNumber];
targets=[];
bases=[];
for(territory in computerPlayer.territories)
{
GameLog("player " +(playerNumber+1) + " scanning territory for attack options: " + computerPlayer.territories[territory]);
base=computerPlayer.territories[territory];
if(g.grid[base].dice>1)
{
attackOptions=g.CanAttack(playerNumber,base);
for(option in attackOptions)
{
target=attackOptions[option];
rand=random(100);
if(rand>10 && g.grid[base].dice>g.grid[target].dice)
{
GameLog(" base:" + base + " > " + target);
targets.push(target);
bases.push(base);
}
if(g.grid[base].dice==g.grid[target].dice)
{
if(rand>50 || g.grid[target].dice==g.maxDice)
{
if(computerPlayer.territories.length>g.grid.length/6 || computerPlayer.reserve>=20) {
GameLog(" base:" + base + " > " + target);
targets.push(target);
bases.push(base);
}
else {
if(g.FindConnected(playerNumber)+computerPlayer.reserve>=8) {
GameLog(" base:" + base + " > " + target);
targets.push(target);
bases.push(base);
}
}
}
}
if(rand>90 && g.grid[base].dice==(g.grid[target].dice-1))
{
if(computerPlayer.territories.length>g.grid.length/6) {
GameLog(" base:" + base + " >-1 " + target);
targets.push(target);
bases.push(base);
}
}
}
}
}
if(targets.length==0) return false;
if(targets.length==1 || targets.length==2) attackQuantity=targets.length;
else attackQuantity=random(targets.length-2)+2;
GameLog("targets: " + attackQuantity);
for(attackNum=0;attackNum<attackQuantity;attackNum++)
{
GameLog("computer " + (playerNumber+1) + " attacking: " + targets[attackNum] + " from: " + bases[attackNum]);
attackFrom=g.grid[bases[attackNum]];
attackTo=g.grid[targets[attackNum]];
if(attackFrom.dice>1 && attackTo.player!=playerNumber) Battle(attackFrom,attackTo,gameNumber);
}
return true;
}
function Quit(err)
{
console.ctrlkey_passthru=oldpass;
bbs.sys_status&=~SS_MOFF;
file_remove(userFileName);
console.clear();
//TODO: CREATE A GAME EXIT ANSI SCREEN
printf("\n\r\1r\1h Thanks for playing!\r\n\r\n");
mswait(1000);
exit(0);
}
//#######################MAIN GAME CLASS###################################
function GameStatusInfo()
{
this.inProgress=[];
this.notFull=[];
this.completed=[];
this.youWin=[];
this.yourGames=[];
this.yourTurn=[];
this.eliminated=[];
this.gameData=[];
this.singleGames=[];
//TODO: REWORK SCOREFILE CODE....BECAUSE IT SUCKS
this.StoreRankings=function()
{
sfilename=game_dir+scorefile+".DAT";
var sfile=new File(sfilename);
if(!Locked(scorefile,true))
{
GameLog("storing rankings in file: " + sfilename);
Lock(scorefile);
sfile.open('w+', false);
for(score in scores) //WHERE SCORE IS USER NUMBER
{
GameLog("storing score: " + scores[score].score + " for user: " + system.username(score));
sfile.writeln(score);
sfile.writeln(scores[score].score); // scorescoer..score score score... SCORES SCORE SCORE! SCORE
sfile.writeln(scores[score].wins);
sfile.writeln(scores[score].losses);
}
sfile.close();
Unlock(scorefile);
}
}
this.LoadRankings=function()
{
var reset=true;
while(reset)
{
reset=false;
data=[];
sfilename=game_dir+scorefile+".DAT";
var lfile=new File(sfilename);
if(file_exists(sfilename))
{
GameLog("loading scores from file: " + sfilename);
lfile.open('r',true);
for(sc=0;!(lfile.eof);sc++)
{
plyr=lfile.readln();
if(plyr==undefined || plyr=="") break;
else
{
player=parseInt(plyr);
var score=parseInt(lfile.readln());
if(score>=pointsToWin)
{
this.ResetScores();
reset=true;
}
var wins=parseInt(lfile.readln());
var losses=parseInt(lfile.readln());
data[player]={'score':score,'wins':wins,'losses':losses};
}
}
lfile.close();
}
else GameLog("score file: " + sfilename + " does not exist");
}
return data;
}
this.ResetScores=function()
{
//TODO: ADD BULLETIN OUTPUT METHOD FOR BULLSEYE BULLETINS & HISTORICAL WINNERS LIST
}
this.LoadGame=function(gamefile,gameNumber,lastModified)
{
humans=0;
var gfile=new File(gamefile);
gfile.open('r',true);
var lgame;
var status=parseInt(gfile.readln());
if(status<0)
{
var minp=parseInt(gfile.readln());
var maxp=parseInt(gfile.readln());
lgame=new NewGame(minp,maxp,gameNumber);
lgame.lastModified=lastModified;
lgame.fileName=gamefile;
if(minp==maxp) lgame.fixedPlayers=true;
for(nnn=0;!(gfile.eof) && nnn<maxp;nnn++)
{
userNumber=gfile.readln();
if(userNumber==undefined || userNumber=="") break;
else
{
userNumber=parseInt(userNumber);
vote=gfile.readln();
lgame.addPlayer(userNumber,parseInt(vote));
if(userNumber>0)
{
if(!scores[userNumber])
{
//INITIALIZE ALL PLAYERS WHO HAVE NO SCORE ENTRY AS ZERO POINTS ZERO WINS
scores[userNumber]={'score':0,'wins':0,'losses':0};
}
}
}
}
gfile.close();
return lgame;
}
var np=parseInt(gfile.readln());
var ms=parseInt(gfile.readln());
var nt=parseInt(gfile.readln());
var r=parseInt(gfile.readln());
var c=parseInt(gfile.readln());
var pt=parseInt(gfile.readln());
lgame=new Map(c,r,np,gameNumber);
lgame.lastModified=lastModified;
lgame.fileName=gamefile;
lgame.mapSize=ms;
lgame.nextTurn=nt;
lgame.status=status;
lgame.playerTerr=pt;
for(to=0;to<np;to++)
{
ttoo=parseInt(gfile.readln());
lgame.turnOrder[to]=ttoo;
}
for(pl=0;pl<np;pl++)
{
u=parseInt(gfile.readln());
res=parseInt(gfile.readln());
bc=bColors[pl];
bfc=bfColors[pl];
fc=fColors[pl];
if(u>0)
{
humans++;
if(scores[u]);
else
{
scores[u]={'score':0,'wins':0,'losses':0};
}
}
lgame.players[pl]=new Player(u,pt);
lgame.players[pl].setColors(pl);
lgame.users[u]=pl;
lgame.players[pl].reserve=res;
}
if(humans<2)
{
lgame.singlePlayer=true;
GameLog("single player game");
}
for(sec=0;sec<ms;sec++)
{
spot_player=parseInt(gfile.readln());
spot_index=parseInt(gfile.readln());
spot_dice=parseInt(gfile.readln());
lgame.grid[spot_index]=new Territory(spot_index);
lgame.used[spot_index]=true;
lgame.grid[spot_index].assign(spot_player,lgame.players[spot_player]);
lgame.players[spot_player].territories.push(spot_index);
lgame.grid[spot_index].dice=spot_dice;
}
lgame.SetGrid();
lgame.SetEliminated();
lgame.CountDiceAll();
GameLog("game " + gameNumber + " loaded");
gfile.close();
return lgame;
}
this.StoreGame=function(gameNumber)
{
g=this.gameData[gameNumber];
GameLog("Storing game: " + gameNumber);
var gamefullname=GetFileName(gameNumber);
var gfile=new File(gamefullname);
gfile.open('w+',false);
gfile.writeln(g.status);
if(g.status<0)
{
gfile.writeln(g.minPlayers);
gfile.writeln(g.maxPlayers);
for(nnn=0;nnn<g.players.length;nnn++)
{
gfile.writeln(g.players[nnn].user);
gfile.writeln(g.players[nnn].vote);
}
gfile.close();
return;
}
gfile.writeln(g.maxPlayers);
gfile.writeln(g.mapSize);
gfile.writeln(g.nextTurn);
gfile.writeln(g.rows);
gfile.writeln(g.columns);
gfile.writeln(g.playerTerr);
for(to=0;to<g.maxPlayers;to++)
{
gfile.writeln(g.turnOrder[to]);
}
for(ply in g.players)
{
p=g.players[ply];
gfile.writeln(p.user);
gfile.writeln(p.reserve);
}
for(sector in g.used)
{
location=sector;
gfile.writeln(g.grid[location].player);
gfile.writeln(g.grid[location].location);
gfile.writeln(g.grid[location].dice);
}
gfile.close();
}
this.UpdateGames=function()
{
GameLog("updating game data");
for(gd in this.gameData)
{
var fileName=this.gameData[gd].fileName;
var lastModified=file_date(fileName);
if(file_exists(fileName))
{
if(lastModified>this.gameData[gd].lastModified)
{
GameLog("game " + gd + " needs updating");
this.gameData[gd]=this.LoadGame(fileName,gd,lastModified);
this.FilterData();
}
}
else
{
GameLog("gamefile " + fileName + " deleted, removing data");
for(gnf in this.notFull) {
if(this.notFull[gnf]==gd) {
this.notFull.splice(gnf,1);
}
}
for(yg in this.yourGames) {
if(this.yourGames[yg]==gd) {
this.yourGames.splice(yg,1);
}
}
delete this.gameData[gd];
}
}
this.inProgress=this.SortArray(this.inProgress);
this.notFull=this.SortArray(this.notFull);
this.completed=this.SortArray(this.completed);
this.youWin=this.SortArray(this.youWin);
this.yourGames=this.SortArray(this.yourGames);
this.yourTurn=this.SortArray(this.yourTurn);
this.eliminated=this.SortArray(this.eliminated);
this.singleGames=this.SortArray(this.singleGames);
}
this.SortArray=function(data)
{
var numItems=data.length;
for(n=0;n<numItems;n++)
{
for(m = 0; m < (numItems-1); m++)
{
if(parseInt(data[m]) > parseInt(data[m+1]))
{
holder = data[m+1];
data[m+1] = data[m];
data[m] = holder;
}
}
}
return data;
}
this.FilterData=function()
{
this.singleGames=[]; //TODO: FIX SINGLEPLAYER GAME DISPLAY TO SHOW ONLY FOR INVOLVED PLAYER
this.inProgress=[];
this.notFull=[];
this.completed=[];
this.youWin=[];
this.yourGames=[];
this.yourTurn=[];
this.eliminated=[];
for(ggg in this.gameData)
{
var gm=this.gameData[ggg];
var playerNumber=gm.users[user.number];
if(gm.users[user.number]>=0)
{
if(gm.status<0) this.notFull.push(ggg);
if(gm.singlePlayer) this.singleGames.push(ggg);
this.yourGames.push(ggg);
if(gm.status==0)
{
this.completed.push(ggg);
if(gm.winner==user.number) this.youWin.push(ggg);
}
else if(gm.status>0)
{
this.inProgress.push(ggg);
if(gm.turnOrder[gm.nextTurn]==playerNumber || gm.singlePlayer)
this.yourTurn.push(ggg);
}
if(gm.players[playerNumber].eliminated==true) this.eliminated.push(ggg);
}
else
{
if(gm.status<0) this.notFull.push(ggg);
else if(!gm.singlePlayer)
{
if(gm.status==0)
{
this.completed.push(ggg);
if(gm.winner>=0)
{
if(gm.winner==user.number) this.youWin.push(ggg);
}
}
}
}
}
}
this.LoadGames=function()
{
var open_list=directory(game_dir + root + "*.DAT"); // scan for voting topic files
GameLog("today's date: " + time());
if(open_list.length)
{
for(lg in open_list)
{
var temp_fname=file_getname(open_list[lg]);
var lastModified=file_date(open_list[lg]);
var daysOld=(time()-lastModified)/daySeconds;
var gameNumber=parseInt(temp_fname.substring(4,temp_fname.indexOf(".")),10);
GameLog("game " + gameNumber + " last modified: " + daysOld + " ago");
var lgame=this.LoadGame(open_list[lg],gameNumber,lastModified);
this.gameData[gameNumber]=lgame;
}
}
}
this.DeleteOld=function()
{
for(oldgame in this.gameData)
{
daysOld=(time()-this.gameData[oldgame].lastModified)/daySeconds;
if(this.gameData[oldgame].singlePlayer==true && daysOld>=10)
{
GameLog("removing old singleplayer game: " + this.gameData[oldgame].gameNumber)
file_remove(this.gameData[oldgame].fileName);
delete this.gameData[oldgame];
}
}
for(completed in this.completed)
{
gm=this.completed[completed];
daysOld=(time()-this.gameData[gm].lastModified)/daySeconds;
GameLog("game was completed " + daysOld + " days ago");
if(this.gameData[gm].singlePlayer==true)
{
if(daysOld>=1)
{
GameLog("removing old singleplayer game: " + this.gameData[gm].gameNumber)
file_remove(this.gameData[gm].fileName);
delete this.gameData[gm];
}
}
else
{
if(daysOld>=4)
{
GameLog("removing old game: " + gm.gameNumber)
file_remove(this.gameData[gm].fileName);
delete this.gameData[gm];
}
}
}
}
this.SkipPlayers=function()
{
for(inp in this.inProgress)
{
gm=this.gameData[this.inProgress[inp]];
if(gm) daysOld=(time()-gm.lastModified)/daySeconds;
GameLog("game: " + this.inProgress[inp] + " last turn was: " + daysOld + " ago");
if(daysOld>=4 && !gm.singlePlayer)
{
nextTurnPlayer=gm.turnOrder[gm.nextTurn];
GameLog("skipping player: " + system.username(gm.players[nextTurnPlayer].user) + " in game " + this.inProgress[inp]);
gm.Reinforce(nextTurnPlayer);
this.StoreGame(this.inProgress[inp]);
}
}
}
this.Init=function()
{
scores=games.LoadRankings();
this.LoadGames();
games.StoreRankings();
this.FilterData();
this.DeleteOld();
this.SkipPlayers();
}
}
function GameLog(data)
{
logfile.writeln(data);
}
//#########################DICE ROLLING FUNCTIONS############################
function RollDice(a,b)
{ //MAIN DICE ROLLING FUNCTION
var totals=[0,0];
var x=menuColumn; var y=16;
ClearArea(y);
bc=console.ansi(BG_RED);
fc=console.ansi(LIGHTGRAY);
FancyRoll(a,x,y,fc,bc);
xx=x;
yy=y;
for(aa=0;aa<a;aa++)
{
rand=(random(6)+1);
dice[rand].display(xx,yy,fc,bc);
xx+=4;
totals[0]+=rand;
}
mswait(50);
y+=4;
bc=console.ansi(BG_LIGHTGRAY);
fc=console.ansi(RED);
FancyRoll(b,x,y,fc,bc);
xx=x;
yy=y;
for(bb=0;bb<b;bb++)
{
rand=(random(6)+1);
totals[1]+=rand;
dice[rand].display(xx,yy,fc,bc);
xx+=4;
}
console.gotoxy((menuColumn+1),24);
console.cleartoeol();
printf("\1n\1r\1hAttacker: " + totals[0] + "\1n Defender: " + totals[1]);
return totals;
}
function FancyRoll(qty,x,y,fc,bc)
{ //"ROLLING DICE" DISPLAY
for(roll=0;roll<8;roll++)
{
xx=x;
yy=y;
for(dr=0;dr<qty;dr++)
{
dice[random(6)+1].display(xx,yy,fc,bc);
xx+=4;
}
mswait(40);
}
}
function Die(number)
{ //DICE CLASS
this.number=number;
this.line1=" ";
this.line2=" ";
this.line3=" ";
this.dot="\xFE";
if(this.number==2 || this.number==3)
{
this.line1=this.dot+" ";
this.line3=" "+this.dot;
}
if(this.number==4 || this.number==5 || this.number==6)
{
this.line1=this.dot+" "+this.dot;
this.line3=this.dot+" "+this.dot;
}
if(this.number==1 || this.number==3 || this.number==5)
this.line2=" "+this.dot+" ";
if(this.number==6)
this.line2=this.dot+" "+this.dot;
this.display=function(x,y,b,f)
{
console.gotoxy(x,y); y++;
printf(f + b + this.line1);
console.gotoxy(x,y); y++;
printf(f + b + this.line2);
console.gotoxy(x,y);
printf(f + b + this.line3);
printf(blackBG);
}
}
function LoadDice()
{ //INITIALIZE SIX SIDED DICE OBJECTS
dice_=[];
for(d=1;d<=6;d++)
{
dice_[d]=new Die(d);
}
return dice_;
}
                                                                               G G G G GG    G G G  G GG G G G  G G G G GG  p pp       p pp    p pp p pp    p pp p pp    p pp p pp GG G  G G G     GG G   G G G  G G G   GG G  GG G   p p p        p p p     p p p  p p p     p p p  p p p     p p p  p p p G GG G GG     G GG  G GG  G GG   G GG G GG  p pp       p pp    p pp p pp    p pp p pp    p pp p pp                                                                                G GG   G GG  G GG  G GG      G GG      p pp       p pp  p pp     p pp  p pp   p pp     p pp  G G G    GG G   G G G   GG G       G G G       p p p        p p p   p p p      p p p   p p p    p p p      p p p G GG   G GG  G GG  G GG      G GG G GG  p pp       p pp  p pp p pp p pp  p pp   p pp     p pp                               GG G                      p p p                        G G G   G GG  G GG  G G G      G G G G GG  p pp  p pp  p pp  p pp p pp p pp  p pp p pp     p pp    G G G    G G G  G GG   GG G       G G G       p p p   p p p   p p p   p p p      p p p   p p p  p p p      p p p    G GG   G GG  G GG   G GG       G GG      p pp  p pp  p pp  p pp     p pp  p pp p pp     p pp                                                                                    G G G G G G     G G G  G G G G G G   G G G G GG    p pp   p pp    p pp     p pp  p pp   p pp  p pp p pp GG G  GG G     GG G   G G G  G G G   GG G  GG G     p p p    p p p     p p p      p p p   p p p    p p p   p p p  p p p G G G  G GG     G G G   G GG  G GG   G G G G GG    p pp   p pp    p pp     p pp  p pp   p pp  p pp p pp                                                                                                 For Synchronet v 3. 14+ - [ HTTP: / / SYNCHRO. NET]                                                                                                          B y M a t t J o h n s o n [ 2008] - T h e B R o K E N B u B B L E B B S [ HTTP: / / MDJ. ATH. CX]       
\ No newline at end of file
//##########################DISPLAY FUNCTIONS#################################
function ClearLine(row,toColumn)
{
console.gotoxy(1,row);
for(col=0;col<toColumn;col++)
{
console.putmsg(" ");
}
}
function ClearArea(fromRow,fromColumn,qty)
{
xx=fromColumn;
yy=fromRow;
for(ccc=0;ccc<qty;ccc++)
{
console.gotoxy(xx,yy); yy++;
console.cleartoeol();
}
}
function Wrap(msg,lst)
{
var coords=console.getxy();
console.putmsg(msg);
console.gotoxy(30,coords.y); coords.y++;
console.putmsg("\1w\1h: ");
if(!lst.length)
{
console.crlf();
return;
}
var bb=0;
var delimiter="\1n\1g,";
for(aa=0;aa<lst.length;aa++)
{
if(bb>=16)
{
var check=console.getxy();
if(check.x>77) {
console.gotoxy(32,coords.y); coords.y++;
bb=0;
}
}
if(aa==lst.length-1) delimiter="";
console.putmsg("\1h\1g" + lst[aa] + delimiter);
bb++;
}
console.crlf();
}
function PrintPadded(string,length,padding,justification)
{
var padlength=length-console.strlen(string);
var newstring=string;
var padded="\1k";
for(p=0;p<padlength;p++) padded+=padding;
if(justification=="left") newstring+=(padded);
if(justification=="right") newstring=(padded + newstring);
return(newstring);
}
function DrawLine(color,length,character)
{
var printchar= "\xC4";
if(character) printchar=character;
for(i=0;i<length;i++) console.putmsg(color + printchar);
}
function DrawVerticalLine(color/*, side*/)
{
var ly=1;
var lx=menuColumn-1;
/* OPTIONAL CODE FOR BOXING IN GAME AREA
var topside="\xB4";
var bottomside="\xD9";
//PARAMETER FOR DRAWING LEFT-HAND OR RIGHT-HAND SIDE OF BOXED IN AREA
if(side)
{
lx=1;
topside="\xC3";
bottomside="\xC0";
}
console.gotoxy(lx,ly); ly++
console.putmsg(color + "\xB3");
console.gotoxy(lx,ly); ly++
console.putmsg(color + topside);
*/
for(;ly<=24;ly++)
{
console.gotoxy(lx,ly);
console.putmsg(color + "\xBA");
}
// console.gotoxy(lx,ly);
// console.putmsg(color + bottomside);
}
function WipeCursor(lr) //SEND CURSOR TO BOTTOM RIGHT CORNER OF SCREEN
{
if(lr=="left") { side=1; row=24; }
else { side=79; row=1; }
console.gotoxy(side,row);
}
function GetColor(color, intensity)
{ //TAKE A STRING AND RETURN THE CORRESPONDING ANSI COLOR CODE
if(intensity=="high") inten="\1h";
else inten="\1n";
if(color=="black") return (inten+"\1k");
if(color=="grey") return ("\1k\1h");
if(color=="cyan") return (inten+"\1c");
if(color=="yellow") return (inten+"\1y");
if(color=="green") return (inten+"\1g");
if(color=="white") return (inten+"\1w");
if(color=="red") return (inten+"\1r");
if(color=="blue") return (inten+"\1b");
if(color=="magenta") return (inten+"\1m");
else return false;
}
function QueueMessage(message,x,y)
{
messages.push({'msg':message,'x':x,'y':y});
}
function DisplayMessages()
{
for(mess in messages) {
var x=messages[mess].x;
var y=messages[mess].y;
var msg=messages[mess].msg;
console.gotoxy(x,y+1);
console.putmsg(msg);
console.cleartoeol();
mswait(500);
}
messages=[];
}
function PutMessage(message,x,y)
{
console.gotoxy(x,y+1);
console.putmsg(message);
mswait(750);
console.gotoxy(x,y+1);
console.cleartoeol();
}
function ShowWinner(g)
{
ClearArea(16,menuColumn,9);
console.gotoxy(51,17);
console.putmsg("\1n\1r\1hThis game was won by: ");
console.gotoxy(53,18);
if(g.winner>=0)
{
console.putmsg("\1n\1r\1h" + system.username(g.winner));
}
else
{
console.putmsg("\1n\1r\1hcomputer player");
}
WipeCursor("left");
}
function Locked(fileName,timeOut)
{
var fname=(game_dir+fileName+".lck");
if(file_exists(fname))
{
if(!timeOut) return true;
var max_attempts=20;
for(attempt=0;attempt<max_attempts;attempt++)
{
if(file_exists(fname))
{
mswait(250);
}
else return false;
}
}
else return false;
return true;
}
function Lock(fileName)
{
var fname=(game_dir+fileName+".lck");
var lockfile=new File(fname);
lockfile.open('we', false);
if(!lockfile.is_open)
return false;
else
{
lockfile.close();
activeGame=fileName;
js.on_exit("Unlock(activeGame)");
return fileName;
}
}
function Unlock(fileName)
{
if(fileName==-1 || !fileName) return;
var fname=(game_dir+fileName+".lck");
file_remove(fname);
}
function UnlockAll()
{
var lockList=directory(game_dir + "*.lck");
if(lockList.length)
{
for(lf in lockList)
{
file_remove(lockList[lf]);
}
}
}
function NewGame(minp,maxp,n)
{
this.status=-1;
this.minPlayers=minp;
this.maxPlayers=maxp;
this.gameNumber=n;
this.players=[];
this.users=[];
this.fixedPlayers=false;
this.singlePlayer=false;
this.lastModified=0;
this.fileName="";
this.addPlayer=function(userNumber,vote)
{
GameLog("adding player: " + userNumber + " vote: " + vote);
if(userNumber) this.users[userNumber]=this.players.length;
this.players.push(new Player(userNumber,vote));
}
this.tallyVotes=function()
{
var trueVotes=0;
for(v in this.players)
{
if(this.players[v].user>0 && this.players[v].vote==1)
{
trueVotes++;
GameLog("player " + v + " voted to start");
}
}
GameLog("votes to start: " + trueVotes);
GameLog("human players: " + this.countHumanPlayers());
GameLog("total players: " + this.countPlayers());
if(trueVotes==this.countHumanPlayers())
{
GameLog("true votes meets number of humans");
if(this.countPlayers()>=this.minPlayers)
{
GameLog("number of players meets minimum");
return true;
}
}
else return false;
}
this.countHumanPlayers=function()
{
var count=0;
for(pppp in this.players)
{
if(this.players[pppp].user>0) count++;
}
return count;
}
this.countPlayers=function()
{
var count=0;
for(pppp in this.players)
{
count++;
}
return count;
}
this.GetVote=function(playerNumber)
{
if(this.players[playerNumber].vote==0) return("wait");
else return("start");
}
this.removePlayer=function(playerNumber)
{
this.players.splice(playerNumber,1);
this.users.splice(user.number,1);
}
}
function Map(c,r,p,gn)
{
//OBJECT VARIABLES
this.grid=[]; //ROWS * COLUMNS IN LENGTH, TRACKS GRID OCCUPANCY
this.status=1; //GAME STATUS INDICATOR
this.takingTurn=false;
this.singlePlayer=false;
this.eliminated=[];
this.lastEliminator=-1;
this.lastMapPosition=-1;
this.winner=-1;
this.lastModified=-1;
this.fileName="";
this.gameNumber=gn;
this.rows=r; //MAP ROWS
this.columns=c; //MAP COLUMNS
this.maxDice=maxDice; //MAXIMUM DICE PER TERRITORY
this.maxPlayers=p; //NUMBER OF PLAYERS IN GAME
this.nextTurn=0;
this.playerTerr=-1; //InitIALIZE TERRITORIES PER PLAYER (SET DURING Init BY this.SetMap())
this.used=[]; //InitIALIZE USED MAP SECTORS (FOR GENERATION OF MAP)
this.turnOrder=[]; //InitIALIZE PLAYER TURN ORDER
this.players=[]; //InitIALIZE PLAYER DATA
this.users=[]; //ATTACH SYSTEM USER NUMBER TO GAME PLAYER NUMBER
this.total=this.columns*this.rows; //TOTAL NUMBER OF POSSIBLE GRID LOCATIONS
this.mapSize=-1; //InitIALIZE MAP SIZE (NOT THE SAME AS TOTAL)
this.minTerr=6; //MINIMUM FOR RANDOM TERRITORY GENERATION PER PLAYER
this.maxTerr=11; //MAXIMUM FOR RANDOM TERRITORY GENERATION PER PLAYER
//NOTIFY NEXT PLAYER OF TURN
//TODO: FIGURE OUT WHY THE GAME (OR THE BBS) IS SENDING DUPLICATE TELEGRAM NOTICES FOR THE SAME TURN
this.Notify= function() //NOTIFY NEXT PLAYER OF TURN
{
nextTurn=this.nextTurn;
nextTurnPlayer=this.players[this.turnOrder[nextTurn]].user;
if(nextTurnPlayer>0 && !this.singlePlayer && nextTurnPlayer!=user.number)
{
DeliverMessage(nextTurnPlayer,this.gameNumber);
GameLog("next player notified of turn: " + system.username(nextTurnPlayer));
}
else
{
while(1)
{
if(nextTurn==this.maxPlayers-1) nextTurn=0;
else nextTurn++;
nextTurnPlayer=this.players[this.turnOrder[nextTurn]].user;
if(nextTurnPlayer==this.players[this.turnOrder[this.nextTurn]].user)
{
GameLog("all other human players eliminated, no other players notified");
break;
}
else if(nextTurnPlayer>0 && nextTurnPlayer!=user.number && this.status!=0)
{
DeliverMessage(nextTurnPlayer,this.gameNumber);
GameLog("skipped computer notices, next human user notified of turn: " + system.username(nextTurnPlayer));
break;
}
}
}
}
this.FindDaysOld= function() //DETERMINE THE LAST TIME A GAME FILE WAS MODIFIED (LAST TURN TAKEN)
{
daysOld=(time()-this.lastModified)/daySeconds;
return daysOld;
}
this.CheckElimination= function()
{
GameLog("checking game elimination data");
var numEliminated=this.eliminated.length;
var humans=this.CountActiveHumans();
if(numEliminated==(this.maxPlayers-1) || humans==0)
{
this.status=0;
if(this.lastEliminator==(-1))
{
if(this.singlePlayer)
{
scores[user.number].losses++;
}
GameLog("game over - computer winner");
return true;
}
else
{ //THE GAME IS OVER BECAUSE A HUMAN PLAYER WON
GameLog("game over - player winner");
this.winner=this.lastEliminator;
this.AssignPoints();
return true;
}
}
else return false;
}
this.CountActiveHumans= function()
{
count=0;
for(ply in this.players)
{
if(this.players[ply].user>0 && !this.players[ply].eliminated) count++;
}
return count;
}
this.AssignPoints= function() //TODO: REWORK SCORING SYSTEM COMPLETELY
{
scores=games.LoadRankings();
if(this.singlePlayer)
{
scores[this.winner].wins+=1;
GameLog("adding win to user " + this.winner);
}
else
{
scores[this.winner].score+=2;
GameLog("giving 2 points to user " + this.winner);
}
games.StoreRankings();
}
this.EliminatePlayer= function(playerNumber,eliminator)
{
dead=this.players[playerNumber];
dead.eliminated=true;
this.eliminated.push(playerNumber);
this.lastEliminator=eliminator;
if(dead.user>0)
{
//TODO: SEE SCORING SYSTEM
pointBuffer=7-this.maxPlayers;
pts=points[pointBuffer+(this.eliminated.length-1)];
scores=games.LoadRankings();
scores[dead.user]+=pts;
GameLog("giving " + pts + " points to user " + dead.user + " : actual points stored " + scores[dead.user]);
games.StoreRankings();
}
GameLog("player " + playerNumber + " eliminated");
}
this.SetEliminated= function()
{ //RUNS AT STARTUP, STORING GAME ELIMINATION DATA UPON LOADING EACH GAME
this.eliminated=[];
for(elp in this.players)
{
if(this.players[elp].territories.length<=0)
{
this.eliminated.push(elp);
this.players[elp].eliminated=true;
}
else this.lastEliminator=this.players[elp].user;
}
if(this.status==0) this.winner=this.lastEliminator;
}
this.GetNextTurn= function()
{
GameLog("assigning next turn in turn order");
if(this.nextTurn==this.maxPlayers-1) this.nextTurn=0;
else this.nextTurn++;
nextPlayer=this.turnOrder[this.nextTurn];
while(this.players[nextPlayer].eliminated)
{
if(this.nextTurn==this.maxPlayers-1) this.nextTurn=0;
else this.nextTurn++;
nextPlayer=this.turnOrder[this.nextTurn];
}
}
this.SetMap= function()
{ //SET MAP SIZE
this.playerTerr=this.minTerr+random(this.maxTerr-this.minTerr);
this.mapSize=this.maxPlayers*(this.playerTerr);
}
this.DisplayGrid= function()
{ //DISPLAYS THE LOCATION DATA FOR EACH COMPANY
DrawVerticalLine("\1w\1h");
for(uu in this.used)
{
this.grid[uu].displayBorder(border_color);
}
}
this.SetGrid= function()
{
for(uu in this.used)
{
this.grid[uu].setBorder(this.grid);
}
}
this.Redraw= function()
{
this.DisplayPlayers();
this.DisplayGrid();
this.displayGame();
WipeCursor("left");
}
this.displayGame= function()
{ //DISPLAY EACH PLAYER'S TERRITORIES
for(ply in this.players)
{
for(ter in this.players[ply].territories)
{
territory=this.players[ply].territories[ter];
this.grid[territory].show();
}
}
}
this.getXY= function(place)
{ //TAKE A GRID INDEX, AND RETURNS THE CORRESPONDING X AND Y COORDINATES FOR DISPLAY
x=this.map_column;
y=this.map_row;
x+=((place%this.columns)*2);
y+=(parseInt(index/this.columns));
console.gotoxy(x,y);
return(0);
}
this.Reinforce= function(playerNumber)
{
numDice=this.FindConnected(playerNumber);
placed=this.PlaceDice(playerNumber,numDice);
if(this.winner<0) this.CheckElimination();
this.GetNextTurn();
if(!this.singlePlayer) this.Notify(this.gameNumber);
return placed;
}
this.CanAttack= function(playerNumber,mapLocation)
{ //RETURNS TRUE IF PLAYER : playerNumber CAN ATTACK FROM GRID INDEX : mapLocation
if(mapLocation>=0) //IF A LOCATION IS PROVIDED, RETURN AN ARRAY OF NEIGHBORING TERRITORIES THAT CAN BE ATTACKED
{
GameLog("reference location provided: " + mapLocation);
options=[];
if(this.grid[mapLocation].dice>1)
{
dirs=this.LoadDirectional(mapLocation);
for(dir in dirs)
{
current=dirs[dir];
if(this.grid[current])
{
if(this.grid[current].player!=playerNumber) options.push(current);
}
}
}
if(options.length) return options;
}
else //OTHERWISE, SIMPLY DETERMINE WHETHER THE PLAYER CAN ATTACK AT ALL, AND RETURN TRUE OR FALSE
{
GameLog("no reference location provided");
if(this.players[playerNumber].territories.length==this.players[playerNumber].totalDice) return false;
for(terr in this.players[playerNumber].territories)
{
currentTerritory=this.players[playerNumber].territories[terr];
if(this.grid[currentTerritory].dice>1)
{
dirs=this.LoadDirectional(currentTerritory);
for(dir in dirs)
{
current=dirs[dir];
if(this.grid[current])
{
if(this.grid[current].player!=playerNumber) return true;
}
}
}
}
}
return false;
}
this.LoadDirectional= function(mapLocation)
{
current=this.grid[mapLocation];
n=current.North;
s=current.South;
nw=current.Northwest;
ne=current.Northeast;
sw=current.Southwest;
se=current.Southeast;
dirs=[n,s,nw,ne,sw,se];
return dirs;
}
this.FindConnected= function(playerNumber)
{ //SCANS ENTIRE MAP AND RETURNS THE NUMBER EQUAL TO THE PLAYER'S LARGEST CLUSTER OF CONNECTED TILES
largest_cluster=1;
terr=this.players[playerNumber].territories;
var checked=[];
var counted=[];
var tocheck=[];
y=10;
for(tttt in terr)
{
count=1;
tocheck.push(terr[tttt]);
while(tocheck.length)
{
loc=tocheck.shift();
current=this.grid[loc];
if(!checked[current.location])
{
dirs=ScanProximity(current.location);
for(ddd in dirs)
{
dir=dirs[ddd];
if(this.grid[dir] && !checked[dir])
{
if(this.grid[dir].player==playerNumber)
{
tocheck.push(dir);
if(!counted[dir])
{
count++;
counted[dir]=true;
}
}
}
}
checked[current.location]=true;
}
}
if(count>largest_cluster) largest_cluster=count;
}
return largest_cluster;
}
this.DisplayPlayers= function()
{ //DISPLAY PLAYER INFO (RIGHT SIDE)
xxx=menuColumn;
yyy=menuRow;
for(ply=0;ply<this.maxPlayers;ply++)
{
playerNumber=this.turnOrder[ply];
player=this.players[playerNumber];
if(player.eliminated) { player.bColor=blackBG; player.fColor="\1n\1k\1h"; }
console.gotoxy(xxx,yyy); yyy++;
console.putmsg(PrintPadded(player.bColor + player.fColor + " " + GetUserName(player,playerNumber) + ":",36," ", "left"));
console.gotoxy(xxx,yyy); yyy++;
console.putmsg(player.fColor + player.bColor+ " LAND: " + PrintPadded(player.fColor + player.territories.length,3," ", "right"));
console.putmsg(player.fColor + player.bColor+ " DICE: " + PrintPadded(player.fColor + player.totalDice,3," ", "right"));
console.putmsg(player.fColor + player.bColor+ " RSRV: " + PrintPadded(player.fColor + player.reserve,3," ", "right") + " ");
}
console.print(blackBG);
}
this.ShufflePlayers= function()
{ //Generate TURN ORDER (this.turnOrder[])
for(pp=0;pp<this.maxPlayers;pp++)
{
var rand=random(this.maxPlayers);
if(this.turnOrder[rand]>=0) pp--;
else this.turnOrder[rand]=pp;
}
}
this.GeneratePlayers= function()
{
for(pl=0;pl<this.maxPlayers;pl++)
{
userNumber=this.players[pl].user;
this.users[userNumber]=pl;
this.players[pl].setColors(pl);
this.players[pl].starting_territories=this.playerTerr;
}
this.ShufflePlayers();
}
this.GenerateMap= function()
{ //RANDOMLY Generate NEW LAND
var unused=[];
for(mi=0;mi<this.total;mi++) unused.push(mi);
randa=random(unused.length);
locationa=unused[randa];
this.grid[locationa]=new Territory(locationa);
this.used[locationa]=true;
unused.splice(randa,1);
for(ms=1;ms<this.mapSize;ms++)
{
randb=random(unused.length);
locationb=unused[randb];
prox=ScanProximity(locationb);
if(this.LandNearby(prox, this.used))
{
this.grid[locationb]=new Territory(locationb);
this.used[locationb]=true;
unused.splice(randb,1);
}
else ms--;
}
var territories=[];
for(mt in this.used)
{
territories.push(mt);
}
for(ply in this.players)
{
for(tt=0;tt < this.playerTerr; tt++)
{
rand=random(territories.length);
location=territories[rand];
if(this.grid[location].player>=0) tt--;
else
{
this.grid[location].assign(ply,this.players[ply]);
this.players[ply].territories.push(location);
}
}
this.PlaceDice(ply,this.playerTerr);
}
this.CountDiceAll();
}
this.LandNearby= function(proximity)
{ //CHECK IMMEDIATE AREA FOR LAND
for(px in proximity)
{
location=proximity[px];
if(this.used[location])
{
return true;
}
}
return false;
}
this.PlaceDice= function(playerNum, numDice)
{ //RANDOMLY PLACE X NUMBER OF DICE ON PLAYER TERRITORIES
playerNumber=parseInt(playerNum);
this.CountDice(playerNumber);
toPlace=numDice;
fulldice=false;
placed=[];
GameLog("Player " + (playerNumber+1) + " Placing " + numDice + " reinforcements");
for(sd=0;sd<numDice;sd++)
{
rand=random(this.players[playerNumber].territories.length);
terr=this.players[playerNumber].territories[rand];
if(this.players[playerNumber].totalDice==(this.players[playerNumber].territories.length*this.maxDice)) //IF ALL OF THIS PLAYER'S TERRITORIES HAVE THE MAXIMUM
{ //AMOUNT OF DICE PUSH DICE INTO PLAYER'S RESERVE
GameLog("all territories full");
fulldice=true;
reserveCap=(30-this.players[playerNumber].reserve);
if(reserveCap>0)
{
GameLog("reserve: " + this.players[playerNumber].reserve + " reserve cap: " + reserveCap + " adding: " + toPlace);
if(reserveCap>=toPlace) this.players[playerNumber].reserve+=toPlace;
else this.players[playerNumber].reserve+=reserveCap;
}
return placed;
}
else if(this.grid[terr].dice<this.maxDice)
{
GameLog("dice placed on: " + terr);
this.grid[terr].dice++;
placed.push(terr);
this.players[playerNumber].totalDice++;
toPlace--;
}
else
{
GameLog("territory: " + terr + " full: " + this.grid[terr].dice);
if(this.players[playerNumber].territories.length==1) return placed;
sd--;
}
}
if(this.players[playerNumber].reserve>0)
{
GameLog("placing reserves");
if(this.players[playerNumber].totalDice==(this.players[playerNumber].territories.length*this.maxDice)) //IF ALL OF THIS PLAYER'S TERRITORIES HAVE THE MAXIMUM
{ //AMOUNT OF DICE PUSH DICE INTO PLAYER'S RESERVE
GameLog("all territories full");
fulldice=true;
}
else
{
while(this.players[playerNumber].reserve>0)
{
rand=random(this.players[playerNumber].territories.length);
terr=this.players[playerNumber].territories[rand];
if(this.grid[terr].dice<this.maxDice)
{
this.grid[terr].dice++;
placed.push(terr);
this.players[playerNumber].totalDice++;
this.players[playerNumber].reserve--;
if(this.players[playerNumber].totalDice==(this.players[playerNumber].territories.length*this.maxDice)) //IF ALL OF THIS PLAYER'S TERRITORIES HAVE THE MAXIMUM
{
GameLog("all territories full");
return placed;
}
}
}
}
}
return placed;
}
this.CountDice= function(playerNumber)
{ //COUNT DICE TOTALS FOR EACH PLAYER
this.players[playerNumber].totalDice=0;
for(td in this.players[playerNumber].territories)
{
terr=this.players[playerNumber].territories[td];
this.players[playerNumber].totalDice+=this.grid[terr].dice;
}
}
this.CountDiceAll= function()
{
for(ppp in this.players)
{
this.CountDice(ppp);
}
}
this.Init= function()
{ //InitIALIZE GAME
this.SetMap();
GameLog("map size set");
this.GeneratePlayers();
GameLog("players Generated");
this.GenerateMap(this.columns, this.rows);
GameLog("map Generated");
this.SetGrid();
GameLog("grid set");
}
//END METHODS
}
function Menu(title,x,y,color,hkey_color)
{ //MENU CLASSES
this.title=title;
this.disabled=[];
this.disabled_color="\1k\1h";
this.items=[];
var orig_x=x;
var orig_y=y;
this.showline=function()
{
var yyyy=orig_y;
console.gotoxy(xxxx,yyyy); yyyy++;
console.cleartoeol();
DrawLine("\1w\1h",79); console.crlf();
}
this.display=function()
{
var yyyy=orig_y;
var clear=5;
var cleared=0;
for(i in this.items)
{
if(!this.disabled[i])
{
console.gotoxy(orig_x,yyyy); yyyy++;
console.putmsg(this.items[i].text);
console.cleartoeol();
cleared++;
}
}
for(i=cleared;i<clear;i++)
{
console.gotoxy(orig_x,yyyy); yyyy++;
console.cleartoeol();
}
WipeCursor("right");
}
this.disable=function(item)
{
this.disabled[item]=true;
this.items[item].Init(this.disabled_color,this.disabled_color)
}
this.enable=function(item)
{
this.disabled[item]=false;
this.items[item].Init(color,hkey_color);
}
this.add=function(items)
{
for(i=0;i<items.length;i++)
{
hotkey=this.getHotKey(items[i]);
this.items[hotkey]=new MenuItem(items[i],hotkey,color,hkey_color);
this.items[hotkey].Init(color,hkey_color);
}
}
this.displayTitle=function()
{
printf("\1h\1w" + this.title);
}
this.getHotKey=function(item)
{
keyindex=item.indexOf("~")+1;
return item.charAt(keyindex);
}
this.displayHorizontal=function()
{
ClearLine(1,48);
console.gotoxy(orig_x,orig_y);
for(i in this.items)
{
console.putmsg(this.items[i].text + " ");
}
WipeCursor("left");
}
}
function MenuItem(item,hotkey,color,hkey_color)
{ //MENU ITEM OBJECT
this.displayColor=color;
this.keyColor=hkey_color;
this.item=item;
this.hotkey=hotkey;
this.Init=function(color,hkey_color)
{
this.text=this.item.replace(("~" + hotkey) , (color + "[" + hkey_color + hotkey + color + "]"));
}
}
\ No newline at end of file
function Player(userNumber, vote)
{
this.user=userNumber;
this.territories=[];
this.totalDice=0;
this.bColor="";
this.bfColor="";
this.fColor="";
this.starting_territories=0;
this.reserve=0;
this.eliminated=false;
this.vote=vote;
this.setColors=function(num)
{
this.bColor=console.ansi(bColors[num]);
this.bfColor=console.ansi(bfColors[num]);
this.fColor=fColors[num];
}
this.removeTerritory=function(territory)
{
for(rem in this.territories)
{
if(this.territories[rem]==territory)
{
this.territories.splice(rem,1);
}
}
}
this.countTerritory=function()
{
count=0;
for(tt in this.territories)
{
count++;
}
return count;
}
}
function Territory(location)
{
this.dice=1;
this.player=-1;
this.bColor=-1;
this.fColor=-1;
this.bfColor=-1;
this.x=-1;
this.y=-1;
this.location=location;
this.topLeft=">";
this.topRight="<";
this.bottomLeft=">";
this.bottomRight="<";
this.North=-1;
this.South=-1;
this.Northwest=-1;
this.Northeast=-1;
this.Southwest=-1;
this.Southeast=-1;
//OBJECT METHODS
this.setBorder= function(data)
{ //CHECK PROXIMITY AND ASSIGN BORDER CHARACTERS
proximity=ScanProximity(this.location);
this.North=proximity[0];
this.South=proximity[1];
this.Northwest=proximity[2];
this.Northeast=proximity[3];
this.Southwest=proximity[4];
this.Southeast=proximity[5];
if(!data[this.North])
{
if(!data[this.Northwest]) this.topLeft=".";
if(!data[this.Northeast]) this.topRight=".";
}
if(!data[this.South])
{
if(!data[this.Southwest]) this.bottomLeft="`";
if(!data[this.Southeast]) this.bottomRight="'";
}
}
this.assign= function(number,player)
{ //GIVE PLAYER OWNERSHIP OF THIS TERRITORY
this.player=number;
this.bColor=player.bColor;
this.bfColor=player.bfColor;
this.fColor=player.fColor;
}
this.show= function()
{ //DISPLAY THIS TERRITORY ON THE MAP
// ALTERNATE MAP POSITION DISPLAY
// display=(this.bfColor + ""+ blackBG + this.bColor + this.fColor + " " + this.dice + " " + blackBG + this.bfColor + "");
display=(this.bfColor + "\xFE"+ blackBG + this.bColor + this.fColor + " " + this.dice + " " + blackBG + this.bfColor + "\xFE");
console.gotoxy(this.x-1, this.y);
console.putmsg(display);
}
this.displayBorder= function(color)
{ //DISPLAY THIS TERRITORY'S BORDER ON THE MAP
console.gotoxy(this.x-2, this.y);
printf(color + "<");
console.gotoxy(this.x+4, this.y);
printf(color + ">");
console.gotoxy(this.x-1, this.y-1);
printf(color+this.topLeft);
DrawLine(color,3);
printf(this.topRight);
console.gotoxy(this.x-1, this.y+1);
printf(color+this.bottomLeft)
DrawLine(color,3)
printf(this.bottomRight);
}
this.displaySelected= function(color)
{ //DISPLAY THIS TERRITORY'S BORDER ON THE MAP
console.gotoxy(this.x-2, this.y);
printf(color + "<");
console.gotoxy(this.x+4, this.y);
printf(color + ">");
console.gotoxy(this.x-1, this.y-1);
printf(color+".");
DrawLine(color,3);
printf(color+".");
console.gotoxy(this.x-1, this.y+1);
printf(color+"`")
DrawLine(color,3)
printf(color+"'");
}
this.getXY= function(loc,sc,sr)
{ //ASSIGN DISPLAY COORDINATES FOR MAP
var startX=sc;
var startY=sr;
offset=loc%columns;
if(offset%2==1) startY++;
startX+=(offset*5);
startY+=(parseInt(loc/columns)*2);
this.x=startX;
this.y=startY;
}
this.getXY(this.location,startColumn,startRow);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment