diff --git a/xtrn/tw2/computer.js b/xtrn/tw2/computer.js new file mode 100644 index 0000000000000000000000000000000000000000..3020d8ffec99a929e048b5e92e8c8ce4fdacae48 --- /dev/null +++ b/xtrn/tw2/computer.js @@ -0,0 +1,86 @@ +function ComputerMenu() +{ + console.crlf(); + console.attributes="HW"; + console.writeln("<Computer activated>"); + var showhelp=true; + + for(;;) { + if(showhelp) { + console.crlf(); + console.printfile(fname("computer.asc")); + } + console.attributes="HW"; + console.write("Computer command (?=help)? "); + switch(InputFunc(['?','1','2','3','4','5'])) { + case '?': + showhelp=true; + break; + case '1': + /* 33990 */ + console.crlf(); + console.attributes="Y"; + console.writeln("<Computer deactivated>"); + return; + case '2': + /* 33780 */ + console.write("What sector number is the port in? "); + var sec=console.getnum(sectors.length-1); + if(sec > 0 && sec < sectors.length) { + var sector=sectors.Get(sec); + if(sector.Port==0 || (sector.Fighters>0 && sector.Fighters!=player.Record)) { + console.crlf(); + console.writeln("I have no information about that port."); + break; + } + if(sec==1) { + SolReport(); + } + else { + PortReport(sector); + } + } + break; + case '3': + /* 33830 */ + console.write("What sector do you want to get to? "); + var sec=console.getnum(sectors.length-1); + if(sec > 0 && sec < sectors.length) { + if(sec==player.Sector) { + console.writeln("You are in that sector."); + break; + } + console.crlf(); + console.writeln("Computing shortest path."); + var path=ShortestPath(player.Sector, sec); + if(path==null) { + console.writeln("There was an error in computation between sectors."); + } + else { + console.writeln("The shortest path from sector "+player.Sector+" to sector "+sec+" is:"); + var i; + for(i in path) { + if(i!=0) + console.write(" - "); + console.write(path[i]); + } + } + } + break; + case '4': + /* 33900 */ + console.crlf(); + console.write("Ranking Players."); + TWRank(); + console.printfile(Settings.TopTenFile); + break; + case '5': + /* 33960 */ + SendRadioMessage(); + break; + default: + console.crlf(); + console.writeln("Invalid command. Enter ? for help"); + } + } +} diff --git a/xtrn/tw2/input.js b/xtrn/tw2/input.js new file mode 100644 index 0000000000000000000000000000000000000000..c012f170b6e9def7495009dd699bb78114154146 --- /dev/null +++ b/xtrn/tw2/input.js @@ -0,0 +1,128 @@ +function GetKeyEcho() +{ + var ret=console.getkey().toUpperCase(); + if(ret=="\x0a" || ret=="\x0d") + ret=''; + console.writeln(ret); + return(ret); +} + +var lastmisc=system.node_list[bbs.node_num-1].misc; +var laststatus=system.node_list[bbs.node_num-1].status; +function InputFunc(values) +{ + var str=''; + var pos=0; + var insertmode=true; + var key; + var origattr=console.attributes; + var matchval=''; + + console.line_counter=0; + console.attributes="N"; +InputFuncMainLoop: + for(;;) { + key=console.inkey(100); + if(key == '') { + /* Node status check */ + var newmisc=system.node_list[bbs.node_num-1].misc; + var newstatus=system.node_list[bbs.node_num-1].status; + if(newmisc != lastmisc || newstatus != laststatus) { + console.saveline(); + bbs.nodesync(); + console.write("\r"); + if(console.line_counter!=0) { + console.crlf(); + console.line_counter=0; + } + console.restoreline(); + lastmisc=system.node_list[bbs.node_num-1].misc; + laststatus=system.node_list[bbs.node_num-1].status; + } + + /* Busy loop checking */ + } + else { + switch(key) { + case '\x1b': /* Escape */ + matchval=''; + pos=0; + break InputFuncMainLoop; + case '\r': + break InputFuncMainLoop; + case '\x08': /* Backspace */ + if(pos==0) + break; + console.write('\x08 \x08'); + str=str.substr(0,-1); + pos--; + /* Fall-through */ + default: + if(key != '\x08') { + /* No CTRL chars (evar!) */ + if(ascii(key)<32) + break; + str=str.substr(0,pos)+key+str.substr(pos); + pos++; + console.write(key); + } + /* Is this an exact match AND the longest possible match? */ + var value; + var exact_match=false; + var longer_match=false; + matchval=''; + for(value in values) { + if(typeof(values[value])=='string') { + var ucv=values[value].toUpperCase(); + var ucs=str.toUpperCase(); + if(ucv==ucs) { + exact_match=true; + matchval=values[value]; + } + else if(ucv.indexOf(ucs)==0) + longer_match=true; + } + else if(typeof(values[value])=='object') { + var min=0; + var max=4294967295; + var def=0; + if(values[value].min != undefined) + min=values[value].min; + if(values[value].max != undefined) + max=values[value].max; + if(values[value].def != undefined) + def=values[value].def; + if(str.search(/^[0-9]*$/)!=-1) { + var cur=def; + if(pos > 0) + cur=parseInt(str); + if(cur >= min && cur <= max) { + exact_match=true; + matchval=cur; + } + if(cur*10 <= max) + longer_match=true; + } + } + } + if(exact_match && !longer_match) + break InputFuncMainLoop; + /* That's not valid! */ + if((!longer_match) && pos > 0) { + console.write('\x08 \x08'); + str=str.substr(0,-1); + pos--; + } + } + } + } + + while(pos > 0) { + console.write('\x08'); + pos--; + } + console.cleartoeol(origattr); + console.write(matchval.toString()); + console.crlf(); + return(matchval); +} diff --git a/xtrn/tw2/maint.js b/xtrn/tw2/maint.js new file mode 100644 index 0000000000000000000000000000000000000000..1ed5c62311c6e5524f52b5650a49fe864354b2ab --- /dev/null +++ b/xtrn/tw2/maint.js @@ -0,0 +1,383 @@ +var CabalProperties = [ + { + prop:"Sector" + ,name:"Sector" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"Size" + ,name:"Size" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"Goal" + ,name:"Goal" + ,type:"Integer" + ,def:0 + } + ]; + +var cabals=new RecordFile(fname("cabal.dat"), CabalProperties); + +function RunMaint() +{ + Settings.MaintLastRan = system.datestr(); + Settings.save(); + console.attributes="HY"; + console.writeln("Running maintence program..."); + console.crlf(); + console.crlf(); + console.writeln("Trade Wars maintence program"); + console.writeln(" by Chris Sherrick (PTL)"); + console.crlf(); + console.writeln("This program is run once per day."); + twmsg.writeln(system.timestr()+": "+user.alias+": Maintence program ran"); + + DeleteInactive(); + + console.crlf(); + + MoveCabal(); +} + +function DeleteInactive() +{ + console.writeln("Deleting inactive players"); + var oldest_allowed=today-Settings.DaysInactivity*86400; + for(i=1; i<players.length; i++) { + var p=players.Get(i); + if(p.UserNumber > 0) { + if((!file_exists(system.data_dir+format("user/%04d.tw2",p.UserNumber))) || (system.datestr(p.LastOnDay) < oldest_allowed && p.KilledBy != 0)) { + DeletePlayer(p) + } + } + } +} + +function MoveCabalGroup(cabal, target) +{ + if(cabal.Sector==0 || cabal.Size < 1) + return; + var sector=sectors.Get(cabal.Sector); + + sector.Fighters -= cabal.Size; + if(sector.Fighters < 1) { + sector.Fighters=0; + sector.FighterOwner=0; + } + sector.Put(); + + /* Set new sector */ + cabal.Sector=target; + sector=sectors.Get(cabal.Sector); + + /* Attack dropped fighters */ + if(sector.Fighters > 0 && sector.FighterOwner != -1) { + var killed=0; + var lost=0; + var ownername="Deleted Player"; + if(sector.FighterOwner > 0) { + var fowner=players.Get(sector.FighterOwner); + ownername=fowner.Alias; + } + while(cabal.Size > 0 && sector.Fighters > 0) { + if(random(2)==1) { + cabal.Size--; + lost++; + } + else { + sector.Fighters--; + killed++; + } + } + /* Place into twpmsg.dat */ + var i; + var msg=null; + for(i=0; i<twpmsg.length; i++) { + msg=twpmsg.Get(i); + if(msg.Read) + break; + msg=null; + } + if(msg==null) + msg=twpmsg.New(); + msg.Read=false; + msg.To=sector.FighterOwner; + msg.From=-1; + msg.Destroyed=killed; + msg.Put(); + twmsg.writeln(" Group "+cabal.Record+" --> Sector "+target+" ("+ownername+"): lost "+killed+", dstrd "+lost+" ("+(sector.Fighters==0?"Player":"Cabal")+" ftrs dstrd)"); + if(cabal.Size==0) { + cabal.ReInit(); + cabal.Put(); + return; + } + else { + sector.FighterOwner=-1; + sector.Fighters=cabal.Size; + } + sector.Put(); + } + + CabalAttack(cabal); + if(cabal.Sector==0 || cabal.Size < 1) + return; + + /* Merge into another group */ + var i; + for(i=1; i<cabals.length; i++) { + if(i==cabal.Record) + continue; + var othercabal=cabals.Get(i); + /* Merge Groups */ + if(othercabal.Sector==cabal.Sector) { + if(othercabal.Record < cabal.Record) { + othercabal.Size += cabal.Size; + cabal.ReInit(); + } + else { + cabal.Size += othercabal.Size; + othercabal.ReInit(); + } + cabal.Put(); + othercabal.Put(); + } + } +} + +function MoveCabal() +{ + var total=0; + var i; + + console.writeln("Moving the Cabal."); + twmsg.writeln(" Cabal report:"); + /* Validate Groups and count the total */ + for(i=1; i<cabals.length; i++) { + var cabal=cabals.Get(i); + var sector=sectors.Get(cabal.Sector); + cabal.Size=sector.Fighters; + if(sector.FighterOwner != -1 || sector.Fighters==0) { + cabal.Sector=0; + cabal.Size=0; + cabal.Goal=0; + } + cabal.Put(); + total+=cabal.Size; + } + + /* Move group 2 into sector 85 (merge into group 1) */ + var cabal=cabals.Get(2); + MoveCabalGroup(cabal, 85); + + /* Note, this seems to have a max limit of 2000 for regeneration */ + var regen=Settings.CabalRegeneration; + if(total+regen > 2000) + regen=2000-total; + if(regen<1) + regen=0; + + cabal=cabals.Get(1); + cabal.Size += regen; + + /* Split off group 2 */ + group2=cabals.Get(2); + if(cabal.Size > 1000) { + group2.Size=cabal.Size-1000; + group2.Sector=85; + MoveCabalGroup(group2, 83); + } + + /* Create wandering groups */ + for(i=3; i<6; i++) { + var wgroup=cabals.Get(i); + if(wgroup.Size < 1 || wgroup.Sector < 1 || wgroup.Sector >= sectors.length) { + if(group2.size >= 600) { + wgroup.Size=100; + group2.size-=100; + wgroup.Sector=83; + wgroup.Goal=0; + while(wgroup.Goal < 8) + wgroup.Goal=random(sectors.length); + } + else { + wgroup.ReInit(); + } + wgroup.Put(); + } + } + + /* Create attack groups */ + for(i=6; i<9; i++) { + var agroup=cabals.Get(i); + if(agroup.Size < 1 || agroup.Sector < 1 || agroup.Sector >= sectors.length) { + if(group2.size >= 550) { + agroup.Size=50; + group2.size-=50; + agroup.Sector=83; + agroup.Goal=0; + while(agroup.Goal < 8) + agroup.Goal=random(sectors.length); + } + else { + agroup.ReInit(); + } + agroup.Put(); + } + } + + /* Create hunter group */ + var hgroup=cabals.Get(9); + if(hgroup.Size < 1 || hgroup.Sector < 1 || hgroup.Sector >= sectors.length) { + if(group2.size >= 500) { + hgroup.Size=group2.Size-500; + group2.size-=hgroup.Size; + hgroup.Sector=83; + hgroup.Goal=0; + } + else { + hgroup.ReInit(); + } + hgroup.Put(); + } + group2.Put(); + + /* Move wandering groups */ + for(i=3; i<6; i++) { + var wgroup=cabals.Get(i); + if(wgroup.Size < 1 || wgroup.Sector == 0) + continue; + /* Choose new target */ + if(wgroup.Sector == wgroup.Goal) { + wgroup.Goal=0; + while(wgroup.Goal < 8) + wgroup.Goal=random(sectors.length); + } + if(wgroup.Size < 50 || wgroup.Size > 100) + wgroup.Goal=85; + var path=ShortestPath(wgroup.Sector, wgroup.Goal); + while(path[0] < 8) + path.shift(); + MoveCabalGroup(wgroup,path[0]); + } + + /* Move Attack Groups */ + for(i=6; i<9; i++) { + var agroup=cabals.Get(i); + if(agroup.Size < 1 || agroup.Sector == 0) + continue; + /* Choose new target */ + if(agroup.Sector == agroup.Goal) { + agroup.Goal=0; + while(agroup.Goal < 8) + agroup.Goal=random(sectors.length); + } + if(agroup.Size < 20 || agroup.Size > 50) + agroup.Goal=85; + var path=ShortestPath(agroup.Sector, agroup.Goal); + var next; + while(path.length > 0 && agroup.Size > 0) { + var next=path.shift(); + if(next < 8) + continue; + MoveCabalGroup(agroup,next); + } + } + + /* Move hunter groups... */ + for(i=9; i<10; i++) { + var hgroup=cabals.Get(i); + if(hgroup.Size < 1 || hgroup.Sector == 0) + continue; + /* Choose target */ + var ranks=RankPlayers(); + if(ranks.length < 0) { + var player=players.Get(ranks[0].Record); + hgroup.Goal=player.Sector; + var path=ShortestPath(hgroup.Sector, hgroup.Goal); + var next; + while(path.length > 0 && hgroup.Size > 0) { + var next=path.shift(); + MoveCabalGroup(agroup,next); + } + } + } +} + +function CabalAttack(cabal) +{ + /* Cabal groups lower than 6 (wandering and defence) do not attack players */ + if(cabal.Record < 6) + return; + + /* Look for another player in the sector (attacking by rank) */ + var i; + var attackwith=0; + + var ranks=RankPlayers(); + var sector=sectors.Get(cabal.Sector); + if(sector.FighterOwner != -1) /* Huh? */ + return; + + sector.Fighters -= cabal.Size; + if(sector.Fighters < 0) + sector.Fighters=0; + + for(i=0; i<ranks.length; i++) { + var otherplayer=players.Get(ranks[i].Record); + + if(otherplayer.Sector != cabal.Sector) + continue; + if(otherplayer.UserNumber==0) + continue; + if(otherplayer.KilledBy != 0) + continue; + else if(cabal.Record<9) /* Attack Group */ + attackwith=20; + else if(cabal.Record==9) { /* Top player hunter */ + if(i==0) + attackwith=cabal.Size; + else + attackwith=0; + } + + if(attackwith==0) + continue; + if(attackwith > cabal.Size) + attackwith = cabal.Size; + + cabal.Size -= attackwith; + /* Attack the player */ + var killed=0; + var lost=0; + while(otherplayer.Fighters > 0 && attackwith > 0) { + if(random(2)==1) { + attackwith--; + lost++; + } + else { + otherplayer.Fighters--; + killed++; + } + } + cabal.Size += attackwith; + twmsg.writeln(" Group "+cabal.Record+" --> "+otherplayer.Alias+": lost "+killed+ ", dstrd "+killed+" ("+(cabal.Size==0?"Cabal":"Player")+" dstrd)"); + if(cabal.Size==0) + cabal.ReInit(); + else { /* Player destroyed by the cabal! */ + otherplayer.KilledBy=-1; + var loc=playerLocation.Get(otherplayer.Record); + loc.Sector=0; + loc.Put(); + } + otherplayer.Put(); + cabal.Put(); + } + sector.Fighters += cabal.Size; + if(cabal.Size > 0) + sector.FighterOwner=-1; + sector.Put(); +} + diff --git a/xtrn/tw2/messages.js b/xtrn/tw2/messages.js new file mode 100644 index 0000000000000000000000000000000000000000..0101793219b4b14ddcfb8268dd21fd66ade0dbd2 --- /dev/null +++ b/xtrn/tw2/messages.js @@ -0,0 +1,168 @@ +var PlayerMessageProperties = [ + { + prop:"Read" + ,name:"Message has been read" + ,type:"Boolean" + ,def:true + } + ,{ + prop:"To" + ,name:"Player the message is to" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"From" + ,name:"Player the message is from" + ,type:"SignedInteger" + ,def:0 + } + ,{ + prop:"Destroyed" + ,name:"Number of Fighters Destroyed" + ,type:"Integer" + ,def:0 + } + ]; + +var RadioMessageProperties = [ + { + prop:"Read" + ,name:"Message has been read" + ,type:"Boolean" + ,def:false + } + ,{ + prop:"To" + ,name:"Player the message is to" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"From" + ,name:"Player the message is from" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"Message" + ,name:"Test of the message" + ,type:"String:74" + ,def:"" + } + ]; + +var twpmsg=new RecordFile(fname("twpmesg.dat"), PlayerMessageProperties); +var twrmsg=new RecordFile(fname("twrmesg.dat"), RadioMessageProperties); + +function ReadPMsg() +{ + console.writeln("The following happened to your ship since your last time on:"); + var count=0; + for(i=0; i<twpmsg.length; i++) { + var msg=twpmsg.Get(i); + + if(msg.To==player.Record && !msg.Read) { + count++; + if(msg.From==-98) + console.writeln("A deleted player destroyed "+msg.Destroyed+" fighters."); + else if(msg.From==-1) { + console.attributes="R"; + console.writeln("The Cabal destroyed "+msg.Destroyed+" fighters."); + } + else { + var otherplayer=players.Get(msg.From); + + console.writeln(otherplayer.Alias+" "+(otherplayer.TeamNumber?" Team["+otherplayer.TeamNumber+"] ":"")+"destroyed "+msg.Destroyed+" of your fighters."); + } + msg.Read=true; + msg.Put(); + } + } + if(count==0) + console.writeln("Nothing"); + return(count); +} + +function RadioMessage(from, to, msg) +{ + var i; + + var rmsg; + for(i=0; i<twrmsg.length; i++) { + var rmsg=twrmsg.Get(i); + if(rmsg.Read) + break; + rmsg=null; + } + if(rmsg==null) + rmsg=twrmsg.New(); + rmsg.Read=false; + rmsg.From=from; + rmsg.To=to; + rmsg.Message=msg; + rmsg.Put(); + console.writeln("Message sent."); + return; +} + +function ReadRadio() +{ + var i; + var rmsg; + var count=0; + + console.crlf(); + console.writeln("Checking for Radio Messages sent to you."); + for(i=0; i<twrmsg.length; i++) { + var rmsg=twrmsg.Get(i); + if(rmsg.Read) + continue; + if(rmsg.To != player.Record) + continue; + console.write("Message from "); + if(rmsg.From > 0) { + var p=players.Get(rmsg.From); + console.write(p.Alias); + } + else { + console.write("A deleted player"); + } + console.writeln(":"); + console.writeln(rmsg.Message); + rmsg.Read=true; + rmsg.Put(); + count++; + } + if(count < 1) + console.writeln("None Received."); +} + +function SendRadioMessage() +{ + console.crlf(); + console.writeln("Warming up sub-space radio."); + mswait(500); + console.crlf(); + console.write("Who do you wish to send this message to (search string)? "); + var sendto=console.getstr(42); + var p=MatchPlayer(sendto); + if(p==null) + return(false); + console.writeln("Tuning in to " + p.Alias + "'s frequency."); + console.crlf(); + console.writeln("Due to the distances involved, messages are limited to 74 chars."); + console.writeln("Pressing [ENTER] with no input quits"); + console.writeln(" [------------------------------------------------------------------------]"); + console.attributes="HY"; + console.write("? "); + console.attributes="W"; + var msg=console.getstr(74); + if(msg==null) + return(false); + msg=msg.replace(/\s*$/,''); + if(msg=='') + return(false); + RadioMessage(player.Record, p.Record, msg); + return(true); +} diff --git a/xtrn/tw2/planets.js b/xtrn/tw2/planets.js new file mode 100644 index 0000000000000000000000000000000000000000..c4341220154d8f2dd2465edebf80c5e365f76649 --- /dev/null +++ b/xtrn/tw2/planets.js @@ -0,0 +1,324 @@ +var PlanetProperties = [ + { + prop:"Name" + ,name:"Name" + ,type:"String:42" + ,def:"" + } + ,{ + prop:"Created" + ,name:"Planet has been created" + ,type:"Boolean" + ,def:false + } + ,{ + prop:"Commodities" + ,name:"Commodities" + ,type:"Array:3:Float" + ,def:[0,0,0] + } + ,{ + prop:"Production" + ,name:"Production (units/day)" + ,type:"Array:3:SignedInteger" + ,def:[0,0,0] + } + ,{ + prop:"LastUpdate" + ,name:"Planet last produced" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"Sector" + ,name:"Location of planet" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"OccupiedBy" + ,name:"Occupied By" + ,type:"Integer" + ,def:0 + } + ]; + +var planets=new RecordFile(fname("planets.dat"), PlanetProperties); + +function LandOnPlanet() +{ + console.crlf(); + console.attributes="HY"; + console.writeln("Landing..."); + var sector=sectors.Get(player.Sector); + var planet=null; + if(sector.Planet==0) { + /* TODO: Race condition? */ + CreatePlanet(sector); + } + else { + /* 32310 */ + /* Lock the planet file and ensure we can land... */ + if(!Lock(planets.file.name, bbs.node_num, true, 5)) { + console.writeln("The spaceport is busy. Try again later."); + return; + } + planet=planets.Get(sector.Planet); + if(planet.OccupiedBy != 0) { + console.writeln("The spaceport is busy. Try again later."); + Unlock(planets.file.name); + return; + } + planet.OccupiedBy=player.Record; + planet.Put(); + Unlock(planets.file.name); + player.Landed=true; + player.Put(); + + Production(planet); + PlanetReport(planet); + console.attributes="HW"; + PlanetMenu(planet); + + if(!Lock(planets.file.name, bbs.node_num, true, 10)) + twmsg.writeln("!!! Error locking planets file!"); + planet.OccupiedBy=0; + planet.Put(); + Unlock(planets.file.name); + player.Landed=false; + player.Put(); + } +} + +function CreatePlanet(sector) +{ + console.writeln("There isn't a planet in this sector."); + console.writeln("Planets cost 10,000 credits."); + if(player.Credits < 10000) { + console.writeln("You're too poor to buy one."); + return(false); + } + console.writeln("You have " + player.Credits + " credits."); + console.write("Do you wish to buy a planet(Y/N) [N]? "); + if(GetKeyEcho()=='Y') { + var i; + var planet; + for(i=1; i<planets.length; i++) { + planet=planets.Get(i); + if(!planet.Created) + break; + planet=null; + } + if(planet==null) { + console.crlf(); + console.writeln("I'm sorry, but all planets are taken."); + console.writeln("One has to be destroyed before you can buy a planet."); + return(false); + } + + planet.Name=''; + console.write("What do you want to name this planet? (41 chars. max)? "); + planet.Name=console.getstr(41); + if(planet.Name=='') + return(false); + for(i=0; i<Commodities.length; i++) { + planet.Commodities[i]=1; + planet.Production[i]=1; + } + player.Credits-=10000; + player.Put(); + planet.Sector=sector.Record; + sector.Planet=planet.Record; + planet.LastUpdated=time(); + planet.Put(); + sector.Put(); + twmsg.writeln(" - "+player.Alias+" made a planet: "+planet.Name); + console.crlf(); + console.writeln("Planet created"); + return(true); + } +} + +function PlanetReport(planet) +{ + console.crlf(); + console.attributes="HC"; + console.writeln("Planet: "+planet.Name); + console.writeln(" Item Prod. Amount in holds"); + console.attributes="HK"; + console.writeln(" ==== ===== ====== ========"); + var i; + var freeholds=player.Holds; + for(i=0; i<Commodities.length; i++) { + console.attributes=['HR','HG','HY','HB','HM','HC','HW'][i]; + console.writeln(format("%s %2d %6d %8d" + ,Commodities[i].disp + ,planet.Production[i] + ,parseInt(planet.Commodities[i]) + ,player.Commodities[i])); + freeholds-=player.Commodities[i]; + } + console.attributes="HG"; + console.writeln("You have "+freeholds+" free cargo holds."); +} + +function PlanetMenu(planet) +{ + var key; + var freeholds=player.Holds; + var i; + var values=new Array('A','I','D','L','R'); + + for(i=0; i<Commodities.length; i++) { + freeholds-=player.Commodities[i]; + values.push((i+1).toString()); + } + + while(true) { + console.crlf(); + console.write("Planet command (?=help)[A]? "); + key=InputFunc(values); + switch(key) { + case '': + case 'A': + console.writeln("<Take all>"); + freeholds = PlanetTakeAll(planet, freeholds); + break; + case 'I': + console.writeln("<Increase productivity>"); + PlanetIncreaseProd(planet); + break; + case 'D': + if(DestroyPlanet(planet)) + return; + break; + case 'L': + return; + case 'R': + PlanetReport(planet); + break; + case '?': + console.crlf(); + console.printfile(fname("planet.asc")); + break; + default: + var keynum=parseInt(key); + if(keynum > 0 && keynum <= Commodities.length) + freeholds=PlanetTakeCommodity(planet, keynum, freeholds); + else + console.writeln("Invalid command. Enter ? for help"); + } + } +} + +function DestroyPlanet(planet) +{ + console.crlf(); + console.attributes="RI7H"; + console.writeln("*** DESTROY THE PLANET ***"); + console.crlf(); + console.attributes="Y"; + console.write("Are you sure (Y/N)[N]? "); + if(GetKeyEcho()=='Y') { + planet.Created=false; + var sector=sectors.Get(planet.Sector); + sector.Planet=0; + planet.Sector=0; + planet.Put(); + sector.Put(); + twmsg.writeln(" - " + player.Alias + " destroyed the planet in sector " + sector.Record); + console.writeln("Planet destroyed."); + return(true); + } + return(flase); +} + +function PlanetTakeAll(planet, freeholds) +{ + if(freeholds < 1) { + console.writeln("You don't have any free holds."); + return(freeholds); + } + for(i=Commodities.length-1; i>=0; i--) { + var take=parseInt(planet.Commodities[i]); + if(take > freeholds) + take=freeholds; + if(take) { + console.writeln("You took " + take + " holds of "+Commodities[i].name.toLowerCase()); + player.Commodities[i]+=take; + planet.Commodities[i]-=take; + freeholds-=take; + } + if(freeholds < 1) { + console.writeln("Your cargo holds are full."); + break; + } + } + player.Put(); + planet.Put(); + return(freeholds); +} + +function PlanetIncreaseProd(planet) +{ + console.crlf(); + console.writeln("You have "+player.Credits+" credits."); + var opts=""; + var values=new Array(); + for(i=0; i<Commodities.length; i++) { + console.writeln((i+1)+" - "+Commodities[i].name+" costs "+(Commodities[i].price*20)); + if(i) + opts += ','; + opts += (i+1).toString(); + values.push((i+1).toString()); + } + console.write("Which one do you want to increase ("+opts+")? "); + var keynum=parseInt(InputFunc(values)); + if(keynum > 0 && keynum <= Commodities.length) { + keynum--; + if(planet.Production[keynum]>19) { + console.writeln("It's at its maximum value."); + return; + } + var max=parseInt(player.Credits/(Commodities[keynum].price*20)); + if(max<1) { + console.writeln("You're too poor. You only have "+player.Credits+" credits."); + return; + } + if(planet.Production[keynum]+max > 19) + max=20-planet.Production[keynum]; + console.write(Commodities[keynum].name+": Increase by how many units? "); + var incr=console.getnum(max); + if(incr > 0 && incr <= max) { + player.Credits -= incr*Commodities[keynum].price*20; + planet.Production[keynum]+=incr; + planet.Put(); + player.Put(); + } + } +} + +function PlanetTakeCommodity(planet, commodity, freeholds) +{ + commodity--; + var max=freeholds; + if(max > parseInt(planet.Commodities[commodity])) + max=parseInt(planet.Commodities[commodity]); + console.writeln("<Take "+Commodities[commodity].name.toLowerCase()+">"); + console.write("How much [" + max + "]? "); + var take=console.getnum(max); + if(take > max) { + console.writeln("They don't have that many."); + return(freeholds); + } + if(take > freeholds) { + console.writeln("You don't have enough free cargo holds."); + return(freeholds); + } + planet.Commodities[commodity]-=take; + player.Commodities[commodity]+=take; + freeholds -= take; + planet.Put(); + player.Put(); + return(freeholds); +} diff --git a/xtrn/tw2/players.js b/xtrn/tw2/players.js new file mode 100644 index 0000000000000000000000000000000000000000..338bf7ec39501d34d5279a4d325b7727a49cc938 --- /dev/null +++ b/xtrn/tw2/players.js @@ -0,0 +1,719 @@ +var PlayerProperties=[ + { + prop:"UserNumber" + ,name:"User Number" + ,type:"Integer" + ,def:(user == undefined?0:user.number) + } + ,{ + prop:"Points" + ,name:"Pointes" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"Alias" + ,name:"Alias" + ,type:"String:42" + ,def:(user == undefined?"":user.alias) + } + ,{ + prop:"LastOnDay" + ,name:"Date Last On" + ,type:"Date" + ,def:system.datestr() + } + ,{ + prop:"KilledBy" + ,name:"Killed By" + ,type:"SignedInteger" + ,def:0 + } + ,{ + prop:"TurnsLeft" + ,name:"Turns Remaining" + ,type:"Integer" + ,def:Settings.TurnsPerDay + } + ,{ + prop:"Sector" + ,name:"Sector" + ,type:"Integer" + ,def:1 + } + ,{ + prop:"Fighters" + ,name:"Fighters" + ,type:"Integer" + ,def:Settings.StartingFighters + } + ,{ + prop:"Holds" + ,name:"Holds" + ,type:"Integer" + ,def:Settings.StartingHolds + } + ,{ + prop:"Commodities" + ,name:"Commodities" + ,type:"Array:3:Integer" + ,def:[0,0,0] + } + ,{ + prop:"Credits" + ,name:"Credits" + ,type:"Integer" + ,def:Settings.StartingCredits + } + ,{ + prop:"TeamNumber" + ,name:"Team Number" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"LastIn" + ,name:"Sector Last In" + ,type:"Integer" + ,def:1 + } + ,{ + prop:"Online" + ,name:"Online" + ,type:"Boolean" + ,def:false + } + ,{ + prop:"Ported" + ,name:"Ported" + ,type:"Boolean" + ,def:false + } + ,{ + prop:"Landed" + ,name:"Landed" + ,type:"Boolean" + ,def:false + } + ]; + +var PlayerLocation = [ + { + prop:"Sector" + ,name:"Sector" + ,type:"Integer" + ,def:1 + } + ]; + +var players=new RecordFile(fname("players.dat"), PlayerProperties); +var playerLocation=new RecordFile(fname("player-loc.dat"), PlayerLocation); + +function AttackPlayer() +{ + var count=0; + var i; + + if(player.Fighters < 1) { + console.writeln("You don't have any fighters."); + return(false); + } + for(i=1;i<players.length; i++) { + var otherloc=playerLocation.Get(i); + if(otherloc.Sector==player.Sector) { + var otherplayer=players.Get(i); + if(otherplayer.Sector==player.Sector + && otherplayer.Record!=player.Record + && otherplayer.KilledBy!=0 + && otherplayer.UserNumber!=0 + && !otherplayer.Online) { + count++; + console.write("Attack "+otherplayer.Alias+" (Y/N)[Y]? "); + if(GetKeyEcho()!='N') { + console.writeln("<Yes>"); + break; + } + } + } + otherplayer=null; + } + if(otherplayer==null) { + if(count) + console.writeln("There are no other ships in here"); + else + console.writeln("There are no ships here to attack."); + return(false); + } + + DoBattle(otherplayer, otherplayer.TeamNumber > 0); + + if(otherplayer.Fighters > 0) + return(true); + + KilledBy(otherplayer, player, true); + /* 15600 player salvages ship from otherplayer */ + var salvaged=parseInt(otherplayer.Holds/4)+1; + if(player.Holds + salvaged > 50) + salvaged=50-player.Holds; + if(salvaged < 1) { + console.writeln("You destroyed the ship, but you can't salvage anything from it"); + return(true); + } + + var j; + + console.writeln("You destroyed the ship and salvaged these cargo holds:"); + var holds=new Array(Commodities.length+1); + for(i=0; i<holds.length+1; i++) + holds[i]=0; + for(i=0; i<otherplayer.Holds; i++) { + var limit=0; + var r=random(otherplayer.Holds)+1; + for(j=0; j<Commodities.length; j++) { + limit += otherplayer.Commodities[j]; + if(r<limit) { + otherplayer.Commodities[j]--; + holds[j]++; + r=0; + break; + } + } + if(r==0) + holds[Commodities.length]++; + } + if(holds[Commodities.length]>0) { + console.writeln(" "+holds[Commodities.length]+" empty."); + player.Holds+=holds[Commodities.length]; + } + for(j=0; j<Commodities.length; j++) { + if(holds[j]>0) { + console.writeln(" "+holds[j]+" with "+Commodities[j].name.toLowerCase()+"."); + player.Holds+=holds[j]; + player.Commodities[j]+=holds[j]; + } + } +} + +function PlayerMove() +{ + if(player.TurnsLeft < 1) { + console.writeln("I'm sorry but you don't have any turns left."); + return(false); + } + console.attributes="HW"; + console.write("Warps lead to: "); + + var sector=sectors.Get(player.Sector); + var i; + var avail=new Array(); + for(i=0; i<sector.Warps.length; i++) { + if(sector.Warps[i]>0) + avail.push(sector.Warps[i].toString()); + } + console.writeln(avail.join(", ")); + console.write("To which sector? "); + var to=InputFunc(sectors.length-1); + if(to=='') + return(false); + return(MoveTo(parseInt(to))); +} + +function PlayerGamble() +{ + console.attributes="HW"; + console.writeln("You have "+player.Credits+" credits."); + console.writeln("How much do you want to gamble at double or nothing (50-50 odds)"); + console.write("[0]? "); + var gamble=console.getnum(player.Credits > 99999?99999:player.Credits); + if(gamble > 0 && gamble <=player.Credits) { + console.write("Flipping the coin..."); + mswait(250); + if(random(2)==1) { + console.crlf(); + player.Credits-=gamble; + console.writeln("Sorry, you lost."); + } + else { + console.crlf(); + player.Credits+=gamble; + console.writeln("You won!"); + } + player.Put(); + console.writeln("You now have "+player.Credits+" credits."); + } +} + +function PlayerInfo(num) +{ + var p=players.Get(num); + + console.attributes="HW"; + console.write(" Pilot's Name: "+p.Alias); + if(p.PlayerNumber>0) + console.write(" Team ["+p.TeamNumber+"]"); + console.crlf(); + console.writeln(" Fighters: "+p.Fighters); + console.attributes="HG"; + console.writeln("Sector Location: "+p.Sector); + console.writeln(" Turns left: "+p.TurnsLeft); + console.writeln(" Cargo Holds: "+p.Holds); + console.attributes="HR"; + var i; + for(i=0; i<Commodities.length; i++) + console.writeln(" # with "+Commodities[i].abbr+": "+p.Commodities[i]+" "); + console.attributes="HM"; + console.writeln(" Credits: "+p.Credits); + console.writeln(" Door points: "+p.Points); +} + +function KilledBy(killed, killer, notify) /* 15300 */ +{ + var i; + + killed.KilledBy=killer.Record; + killed.Put(); + var killedLocation=playerLocation.Get(killed.Record); + killedLocation.Sector=killed.Sector; killedLocation.Put(); + + /* Destroy all deployed fighters */ + for(i=1; i<sectors.length; i++) { + var sector=sectors.Get(i); + if(sector.FighterOwner==player.Record) { + sector.Fighters=0; + sector.FighterOwner=0; + sector.Put(); + } + } + + if(killed.TeamNumber > 0) { + var team=teams.Get(killed.TeamNumber); + var i; + for(i=0; i<team.Members.length; i++) { + if(team.Members[i]==killed.Record) { + team.Members[i]=0; + team.Size--; + } + } + } + + if(notify) + twmsg.writeln(" - "+killer.Alias+" killed "+killed.Alias); +} + +function RankPlayers() +{ + var i; + var rank=new Array(); + var fighters=new Array(); + + for(i=1; i<sectors.length; i++) { + var sector=sectors.Get(i); + if(sector.Fighters > 0 && sector.FighterOwner > 0) { + if(fighters[sector.FighterOwner]==undefined) + fighters[sector.FighterOwner]=0; + fighters[sector.FighterOwner]+=sector.Fighters; + } + } + for(i=1; i<players.length; i++) { + var p=players.Get(i); + if(p.UserNumber==0) + continue; + if(p.KilledBy!=0) + continue; + var robj=new Object(); + robj.Record=p.Record; + robj.Score=p.Fighters*100 + p.Holds*500 + p.Credits; + for(i=0; i<Commodities.length; i++) + robj.Score += Commodities[i].price*p.Commodities[i]; + if(fighters[i]!=undefined) + robj.Score += fighters[i]*100; + rank.push(robj); + } + + function sortfunc(a,b) { + return(a.Score-b.Score); + } + + rank.sort(sortfunc); + return(rank); +} + +function TWRank() +{ + var rf=new File(fname(Settings.TopTenFile)); + rf.open("w"); + rf.writeln(); + rf.writeln(" T R A D E W A R S I I - 500T S C O R E B O A R D "); + rf.writeln(); + rf.writeln("Last updated at: "+system.timestr()); + rf.writeln(); + rf.writeln("Player Rankings"); + rf.writeln("Rank Value Team Player"); + rf.writeln("==== ============= ====== ================"); + var ranked=RankPlayers(); + var i; + var trank=new Object(); + + for(i=0; i<ranked.length; i++) { + var p=players.Get(ranked[i].Record); + if(i<10) + rf.writeln(format("%4d %13d %6s %s",(i+1),ranked[i].Score,p.TeamNumber==0?"":p.TeamNumber.toString(),p.Alias)); + if(p.TeamNumber.toString() != 0) { + if(trank[p.TeamNumber.toString()]==undefined) + trank[p.TeamNumber.toString()]=0; + trank[p.TeamNumber.toString()]+=ranked[i].Score; + } + } + var tsort=new Array(); + for(tr in trank) { + var ts=new Object(); + ts.Record=tr; + ts.Score=trank[tr]; + tsort.push(tr); + } + if(tsort.length > 0) { + function sortfunc(a,b) { + return(a.Score-b.Score); + } + + tsort.sort(sortfunc); + rf.writeln(); + rf.writeln("Team Rankings"); + rf.writeln("Rank Value Team"); + rf.writeln("==== ============= ======"); + for(i=0; i<tsort.length; i++) { + if(i>=10) + break; + rf.writeln(format("%4d %13d %6d",(i+1),tsort[i].Score,tsort[i].Record)); + } + } + rf.close(); +} + +function DoBattle(opp, otherteam) +{ + if(player.Fighters<1) { + console.writeln("You don't have any fighters!"); + return(0); + } + else { + console.write("How many fighters do you wish to use? "); + var use=console.getnum(player.Fighters); + + if(use > 0 && use <= player.Fighters) { + var lost=0; + var killed=0; + + player.Fighters -= use; + while(use && opp.Fighters) { + if(player.TeamNumber > 0 && otherteam) { + if((random(10)+1) > 6) { + opp.Fighters--; + killed++; + } + else { + use--; + lost++; + } + } + else if(otherteam && player.TeamNumber==0) { + if((random(10)+1) > 6) { + use--; + lost++; + } + else { + opp.Fighters--; + killed++; + } + } + else { + if(random(2)==0) { + use--; + lost++; + } + else { + opp.Fighters--; + killed++; + } + } + } + player.Fighters += use; + opp.Put(); + player.Put(); + + console.writeln("You lost "+lost+" fighter(s), "+player.Fighters+" remain."); + if(opp.Fighters > 0) + console.write("You destroyed "+killed+" enemy fighters, "+opp.Fighters+" remain."); + else + console.write("You destroyed all of the enemy fighters."); + return(killed); + } + } + return(0); +} + +function MatchPlayer(name) +{ + var i; + + name=name.toUpperCase(); + for(i=1; i<players.length; i++) { + var p=players.Get(i); + if(p.UserNumber==0) + continue; + if(p.KilledBy!=0) + continue; + if(p.Alias.toUpperCase().indexOf(name)!=-1) { + console.write(p.Alias+" (Y/N)[Y]? "); + switch(GetKeyEcho()) { + case 'N': + break; + default: + return(p); + } + } + } + console.writeln("Not found."); + return(null); +} + +function DeletePlayer(player) +{ + /* Delete player */ + player.ReInit(); + player.UserNumber=0; + player.Alias="<Deleted>"; + player.Sector=0; + player.Put(); + /* Move to sector zero */ + var loc=playerLocation.Get(player.Record); + loc.Sector=0; + loc.Put(); + /* Set fighter owner to "Deleted Player" */ + var i; + for(i=1; i<sectors.length; i++) { + var sector=sectors.Get(i); + if(sector.FighterOwner==player.Record) { + sector.FighterOwner=-98; + sector.Put(); + } + } + /* Set messages TO the deleted player as read and FROM as from deleted */ + for(i=0; i<twpmsg.length; i++) { + var msg=twpmsg.Get(i); + + if(msg.To==player.Record && !msg.Read) { + msg.Read=true; + msg.Put(); + } + else if(msg.From==player.Record) { + msg.From=-98; + msg.Put(); + } + } + /* Set radio messages TO the deleted player as read and FROM as from deleted */ + for(i=0; i<twrmsg.length; i++) { + var msg=twrmsg.Get(i); + + if(msg.To==player.Record && !msg.Read) { + msg.Read=true; + msg.Put(); + } + else if(msg.From==player.Record) { + msg.From=-98; + msg.Put(); + } + } + /* Set killed bys to Deleted Player */ + for(i=1; i<players.length; i++) { + var otherplayer=players.Get(i); + + if(otherplayer.KilledBy==player.Record) { + otherplayer.KilledBy=-98; + otherplayer.Put(); + } + } + twmsg.writeln(" - "+player.Alias+" deleted from game"); +} + +function MoveTo(to) +{ + var sector=sectors.Get(player.Sector); + + if(to > 0) { + for(i=0; i<sector.Warps.length; i++) { + if(sector.Warps[i]==to) { + player.TurnsLeft--; + player.LastIn=player.Sector; + player.Sector=to; + player.Put(); + location.Sector=player.Sector; location.Put(); + if(player.TurnsLeft==10 || player.TurnsLeft < 6) { + console.writeln("You have " + player.TurnsLeft + " turns left."); + } + return(true); + } + } + console.writeln("You can't get there from here."); + } + return(false); +} + +function LoadPlayer() +{ + var firstnew; + for(i=1; i<players.length; i++) { + player=players.Get(i); + if(player.UserNumber == user.number && (!file_exists(system.data_dir+format("user/%04d.tw2",player.UserNumber)))) + DeletePlayer(player); + if(player.UserNumber==0 && firstnew==undefined) + firstnew=player; + if(player.UserNumber == user.number) + break; + } + if(player==undefined || player.UserNumber!=user.number) { + console.attributes="G"; + console.writeln("I can't find your record, so I am assuming you are a new player."); + console.attributes="M"; + console.writeln("Entering a new player..."); + player=firstnew; + if(player==undefined) { + console.writeln("I'm sorry but the game is full."); + console.writeln("Please leave a message for the Sysop so"); + console.writeln("he can save a space for you when one opens up."); + twmsg.writeln(system.timestr()+": New player not allowed - game full."); + return(false); + } + console.crlf(); + console.writeln("Notice: If you don't play this game for "+Settings.DaysInactivity+" days, you will"); + console.writeln("be deleted to make room for someone else."); + console.crlf(); + console.writeln("Your ship is being initialized."); + + /* Lock the player file and mark us online... */ + if(!Lock(players.file.name, bbs.node_num, true, 10)) { + console.writeln("!!!Unable to lock player data!"); + twmsg.writeln("!!!Unable to lock player data!"); + return(false); + } + player.ReInit(); + player.Online=true; + player.Put(); + Unlock(players.file.name); + + twmsg.writeln(system.timestr()+" "+user.alias+": New Player logged on"); + Instructions(); + } + else { + /* Lock the player file and mark us online... */ + if(!Lock(players.file.name, bbs.node_num, true, 10)) { + console.writeln("!!!Unable to lock player data!"); + twmsg.writeln("!!!Unable to lock player data!"); + return(false); + } + player.Online=true; + player.Put(); + Unlock(players.file.name); + + console.crlf(); /* TODO: BASIC magic... N$ appears empty tw2.bas: 242 */ + twmsg.writeln(system.timestr()+" "+user.alias+": Logged on"); + if(today < system.datestr(player.LastOnDay)) { + console.writeln("I'm sorry, but you won't be allowed on for another " + parseInt((system.datestr(player.LastOnDay)-today)/86400) + " day(s)"); + return(false); + } + if(today==system.datestr(player.LastOnDay)) { + if(player.KilledBy != -99) { + console.writeln("You have been on today."); + if(player.TurnsLeft<1) { + console.writeln("You don't have any turns left today. You will be allowed to play tomorrow."); + return(false); + } + if(player.KilledBy==player.Record) { + console.writeln("You killed yourself today. You will be allowed to play tomorrow."); + return(false); + } + ReadPMsg(); + } + } + else { + player.TurnsLeft=Settings.TurnsPerDay; + } + player.LastOnDay=system.datestr(); + if(player.KilledBy != 0) { + switch(player.KilledBy) { + case player.Record: + console.attributes="R"; + console.writeln("You managed to kill yourself on your last time on."); + break; + case -1: + console.attributes="R"; + console.writeln("You have been killed by the Cabal!"); + break; + case -98: + console.writeln("You have been killed by a deleted player."); + break; + default: + var otherplayer=players.Get(player.KilledBy); + + console.writeln(otherplayer.Alias+" destroyed your ship!"); + break; + } + player.ReInit(); + } + } + file_touch(system.data_dir+format("user/%04d.tw2",player.UserNumber)) + + ReadRadio(); + + if(player.Sector < 1 || player.Sector >= sectors.length) { + console.writeln("You are being moved to sector 1"); + player.Sector=1; + player.Put(); + } + location=playerLocation.Get(player.Record); + location.Sector=player.Sector; + location.Put(); + + if(player.Credits > 25000) { + console.crlf(); + console.writeln("Tax time! You are being taxed 5000 credits to help support the resistance"); + console.writeln("against the evil Cabal."); + player.Credits -= 5000; + player.Put(); + } + return(true); +} + +function Dropfighters() +{ + if(player.Sector < 8) { + console.writeln("You can't leave fighters in the Union (sectors 1-7)"); + return(false); + } + var sector=sectors.Get(player.Sector); + if(sector.Fighters > 0 && sector.FighterOwner != player.Record) { + console.writeln("There are already fighters in this sector!"); + return(false); + } + console.writeln("You have " + (player.Fighters+sector.Fighters) + " fighters available."); + console.write("How many fighters do you want defending this sector? "); + var newf=player.Fighters+sector.Fighters; + if(newf > 9999) + newf=9999; + var newf=console.getnum(newf); + if(newf >= 0 && newf <=player.Fighters+sector.Fighters) { + if((player.Fighters+sector.Fighters)-newf > 9999) { + console.writeln("Too many ships in your fleet! You are limited to 9999"); + return(false); + } + player.Fighters=(player.Fighters+sector.Fighters)-newf; + sector.Fighters=newf; + if(sector.Fighters > 0) + sector.FighterOwner=player.Record; + sector.Put(); + player.Put(); + console.writeln("Done. You have " + player.Fighters + " fighter(s) in your fleet."); + return(true); + } + return(false); +} diff --git a/xtrn/tw2/ports.js b/xtrn/tw2/ports.js new file mode 100644 index 0000000000000000000000000000000000000000..5cd3202afd236d80c7f3639652e472f53e29eb47 --- /dev/null +++ b/xtrn/tw2/ports.js @@ -0,0 +1,322 @@ +var PortProperties = [ + { + prop:"Name" + ,name:"Name" + ,type:"String:42" + ,def:"" + } + ,{ + prop:"Class" + ,name:"Class" + ,type:"Integer" + ,def:"" + } + ,{ + prop:"Commodities" + ,name:"Commodities" + ,type:"Array:3:Float" + ,def:[0,0,0] + } + ,{ + prop:"Production" + ,name:"Production (units/day)" + ,type:"Array:3:SignedInteger" + ,def:[0,0,0] + } + ,{ + prop:"PriceVariance" + ,name:"Price Variance (percentage)" + ,type:"Array:3:SignedInteger" + ,def:[0,0,0] + } + ,{ + prop:"LastUpdate" + ,name:"Port last produced" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"OccupiedBy" + ,name:"Occupied By" + ,type:"Integer" + ,def:0 + } + ]; + +var ports=new RecordFile(fname("ports.dat"), PortProperties); + +function DockAtPort() +{ + console.attributes="HR"; + console.crlf(); + console.writeln("Docking..."); + if(player.TurnsLeft<1) { + console.writeln("Sorry, but you don't have any turns left."); + return; + } + var sector=sectors.Get(player.Sector); + if(sector.Port<1) { + console.writeln("There are no ports in this sector."); + return; + } + player.TurnsLeft--; + player.Ported=true; + player.Put(); + console.writeln("One turn deducted"); + if(player.Sector==1) { + DockAtSol(); + } + else { + DockAtRegularPort(); + } + player.Ported=false; + player.Put(); +} + +function DockAtSol() +{ + /* 33200 */ + var prices=SolReport(); + console.attributes="HR"; + console.writeln("You have " + player.Credits + " credits."); + console.crlf(); + /* Holds */ + var maxbuy=parseInt(player.Credits/prices[0]); + if(player.Holds+maxbuy>50) + maxbuy=50-player.Holds; + if(maxbuy > 0) { + console.write("How many holds do you want to buy [0]? "); + var buy=console.getnum(maxbuy); + if(buy>0) { + player.Holds+=buy; + player.Credits -= buy*prices[0]; + player.Put(); + console.writeln("You have " + player.Credits + " credits."); + } + } + /* Fighters */ + var maxbuy=parseInt(player.Credits/prices[1]); + if(player.Fighters+maxbuy>9999) + maxbuy=9999-player.Fighters; + if(maxbuy > 0) { + console.write("How many fighters do you want to buy [0]? "); + var buy=console.getnum(maxbuy); + if(buy>0) { + player.Fighters+=buy; + player.Credits -= buy*prices[1]; + player.Put(); + console.writeln("You have " + player.Credits + " credits."); + } + } + /* Turns */ + var maxbuy=parseInt(player.Credits/prices[2]); + if(maxbuy > 0) { + console.write("How many turns do you want to buy [0]? "); + var buy=console.getnum(maxbuy); + if(buy>0) { + player.TurnsLeft+=buy; + player.Credits -= buy*prices[2]; + player.Put(); + console.writeln("You have " + player.Credits + " credits."); + } + } +} + +function DockAtRegularPort() +{ + var sector=sectors.Get(player.Sector); + + /* Lock the port file and ensure we can dock... */ + if(!Lock(ports.file.name, bbs.node_num, true, 5)) { + console.writeln("The port is busy. Try again later."); + return; + } + var port=ports.Get(sector.Port); + if(port.OccupiedBy != 0) { + console.writeln("The port is busy. Try again later."); + Unlock(ports.file.name); + return; + } + port.OccupiedBy=player.Record; + port.Put(); + Unlock(ports.file.name); + Production(port); + var sale=PortReport(sector); + console.attributes="HR"; + var count=0; + + console.writeln(); + + console.attributes="HY"; + /* Sell... */ + for(i=0; i<Commodities.length; i++) { + if(sale[i].Vary < 0) { + var amount=Transact(i, sale[i].Price, sale[i].Vary, sale[i].Number); + if(amount >= 0) { + count++; + port.Commodities[i] += amount; + port.Put(); + } + } + } + /* Buy... */ + for(i=0; i<Commodities.length; i++) { + if(sale[i].Vary > 0) { + var amount=Transact(i, sale[i].Price, sale[i].Vary, sale[i].Number); + if(amount >= 0) { + count++; + port.Commodities[i] -= amount; + port.Put(); + } + } + } + if(count==0) { + console.attributes="IC"; + console.writeln("You don't have anything they want, and they don't have anything you can buy"); + console.attributes="C"; + } + + if(!Lock(ports.file.name, bbs.node_num, true, 10)) + twmsg.writeln("!!! Error locking ports file!"); + port.OccupiedBy=0; + port.Put(); + Unlock(ports.file.name); +} + + +function PortReport(sec) { + var port=ports.Get(sec.Port); + var i; + + if(port==null) + return(null); + /* 33000 */ + Production(port); + var ret=new Array(Commodities.length); + for(i=0; i<Commodities.length; i++) { + ret[i]=new Object(); + ret[i].Vary=port.PriceVariance[i]; + ret[i].Number=parseInt(port.Commodities[i]); + ret[i].Price=parseInt(Commodities[i].price*(1-ret[i].Vary*ret[i].Number/port.Production[i]/1000)+.5); + } + console.crlf(); + console.writeln("Commerce report for "+port.Name+": "+system.timestr()); + console.crlf(); + console.writeln(" Items Status # units in holds"); + console.attributes="HK"; + console.writeln(" ===== ====== ======= ========"); + for(i=0; i<Commodities.length; i++) { + console.attributes=['HR','HG','HY','HB','HM','HC','HW'][i]; + console.writeln(format("%s %-7s %-7d %-7d", + Commodities[i].disp + ,ret[i].Vary<0?"Buying":"Selling" + ,ret[i].Number + ,player.Commodities[i])); + } + return(ret); +} + +function SolReport() +{ + var holdprice=parseInt(50*Math.sin(.89756*(today/86400)) + .5)+500; + var fighterprice=parseInt(10*Math.sin(.89714*(today/86400) + 1.5707) + .5)+100; + var turnprice=300; + + console.writeln("Commerce report for Sol: " + system.timestr()); + console.writeln(" Cargo holds: " + holdprice + " credits/hold"); + console.writeln(" Fighters : " + fighterprice + " credits/fighter"); + console.writeln(" Turns : "+turnprice+" credits each."); + console.crlf(); + + return([holdprice,fighterprice,turnprice]); +} + +function Transact(type, price, vary, avail) +{ + var buy=vary<0?false:true; + var youare=buy?"buy":"sell"; + var weare=buy?"sell":"buy"; + var emptyholds=player.Holds; + var max=0; + + var i; + for(i=0; i<Commodities.length; i++) + emptyholds -= player.Commodities[i]; + + if(buy) + max=emptyholds; + else + max=player.Commodities[type]; + + if(max > parseInt(avail)) + max=parseInt(avail); + + if(max < 1) + return(-1); + + console.crlf(); + console.writeln("You have "+player.Credits+" credits and "+emptyholds+" empty cargo holds."); + console.crlf(); + console.writeln("We are "+weare+"ing up to "+avail+". You have "+player.Commodities[type]+" in your holds."); + + console.write("How many holds of "+Commodities[type].name.toLowerCase()+" do you want to "+youare+" ["+max+"]? "); + var amount=console.getnum(max,max); + + if(amount>0 && amount<=max) { + var done=false; + console.writeln("Agreed, "+amount+" units."); + var haggles=random(3)+2; + var offer=0; + for(var hag=0; hag<haggles; hag++) { + if(hag==haggles-1) + console.write("Our final offer is "); + else + console.write("We'll "+weare+" them for "); + console.writeln(parseInt(price*amount*(1+vary/1000)+.5)); + offer=0; + while(offer==0) { + console.write("Your offer? "); + offer=console.getnum(buy?player.Credits:(price*amount*10)); + if(offer==0) + break; + if(offer < price*amount/10 || offer > price*amount*10) { + console.writeln("That was pretty funny, Now make a serious offer."); + offer=0; + } + } + if(offer==0) + break; + if(!buy && offer <= price*amount) { + console.writeln("We'll take them!"); + player.Credits += offer; + player.Commodities[type] -= amount; + player.Put(); + return(amount); + } + if(buy && offer >= price*amount) { + console.writeln("Sold!"); + player.Credits -= offer; + player.Commodities[type] += amount; + player.Put(); + return(amount); + } + var worstoffer=parseInt(amount*price*(1-vary/250/(hag+1)) + .5); + if(buy && offer < worstoffer) + break; + if(!buy && offer > worstoffer) + break; + price = .7*price + .3*offer/amount; + } + + if(offer > 0) { + if(buy) { + console.writeln("Too low. We'll sell them to local traders."); + return(0); + } + console.writeln("Too high. We'll buy them from local traders."); + } + return(0); + } + return(0); +} + diff --git a/xtrn/tw2/sectors.js b/xtrn/tw2/sectors.js new file mode 100644 index 0000000000000000000000000000000000000000..fed81561fa7ad5a33d3698ab2c567a45b8b7ebcd --- /dev/null +++ b/xtrn/tw2/sectors.js @@ -0,0 +1,298 @@ +var SectorProperties = [ + { + prop:"Warps" + ,name:"Warps" + ,type:"Array:6:Integer" + ,def:[0,0,0,0,0,0] + } + ,{ + prop:"Port" + ,name:"Port" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"Planet" + ,name:"Planet" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"Fighters" + ,name:"Fighters" + ,type:"Integer" + ,def:0 + } + ,{ + prop:"FighterOwner" + ,name:"Fighters Owner" + ,type:"SignedInteger" + ,def:0 + } + ]; + +var sectors=new RecordFile(fname("sectors.dat"), SectorProperties); + +function CheckSector() +{ + if(player.Sector==85) { + console.crlf(); + console.attributes="W"; + console.writeln("Congratulations! You've defeated the cabal and gained 100,000 points!"); + player.Points += 100000; + player.Put(); + console.writeln("Unfortunately, victory is fleeting..."); + + var sector=sectors.Get(85); + sector.Fighters=3000; + sector.FighterOwner=-1; + sector.Put(); + twopeng.writeln("Congratulations go to "+player.Alias+ + " who invaded the Cabal empire on " + system.datestr() + + " and received 100,000 points!"); + return(false); + } + return(true); +} + +function EnterSector() /* 20000 */ +{ + var sector=sectors.Get(player.Sector); + var fighterteam=-1; + + console.attributes="Y"; + DisplaySector(sector.Record); + if(sector.FighterOwner > 0) { + var otherplayer=players.Get(sector.FighterOwner); + if(otherplayer.TeamNumber > 0) + fighterteam=otherplayer.TeamNumber; + } + while(sector.FighterOwner != player.Record && sector.Fighters > 0 && fighterteam != player.TeamNumber) { + console.writeln("You have to destroy the fighters before you can enter this sector."); + console.writeln("Fighters: "+player.Fighters+" / "+sector.Fighters); + console.write("Option? (A,D,I,Q,R,?):? "); + switch(InputFunc(['A','D','I','Q','R','?'])) { + case 'A': + console.writeln("<Attack>"); + var otherteam=false; + + if(sector.FighterOwner > 0) { + var otherplayer=players.Get(sector.FighterOwner); + if(otherplayer.TeamNumber>0) + otherteam-true; + } + var killed=DoBattle(sector, otherteam); + if(killed > 0) { + player.Points+=k*100; + console.writeln("You just recieved "+(k*100)+" points for that."); + } + if(sector.Fighters==0) + console.writeln("You destroyed all the fighters."); + break; + case 'D': + console.writeln("<Display>"); + DisplaySector(player.Sector); + break; + case 'I': + console.writeln("<Info>"); + PlayerInfo(player.Record); + break; + case 'Q': + console.write("Are you sure (Y/N)? "); + if(console.getkeys("YN")=='Y') { + exit_tw2=true; + return(false); + } + break; + case 'R': + console.writeln("<Retreat>"); + if(player.LastIn<1 || player.LastIn>=sectors.length) + player.LastIn=random(sectors.length-1)+1; + if(player.Fighters<1) { + if(random(2)==1) { + console.writeln("You escaped!"); + player.Sector=player.LastIn; + player.Put(); + location.Sector=player.Sector; location.Put(); + return(false); + } + console.attributes="R"; + console.writeln("You didn't escape!"); + console.writeln("Your ship has been destroyed!"); + console.crlf(); + console.attributes="R"; + console.writeln("You will start over tomorrow with a new ship."); + KilledBy(player, player, true); + return(false); + } + else { + player.Fighters--; + console.writeln("You have "+player.Fighters+" fighter(s) left."); + player.Sector=player.LastIn; + player.Put(); + location.Sector=player.Sector; location.Put(); + return(false); + } + break; + case '': + console.writeln("?=<Help>"); + break; + case '?': + console.writeln("<Help>"); + console.crlf(); + console.printfile(fname("entersector.asc")); + break; + default: + console.crlf(); + console.writeln("Invalid command. ? = Help"); + } + } + return(true); +} + +function DisplaySector(secnum) +{ + var sector=sectors.Get(secnum); + var i; + var count=0; + + console.crlf(); + console.attributes="HY"; + console.writeln("Sector "+secnum); + console.attributes="HR"; + console.write("Port "); + if(sector.Port > 0) { + var port=ports.Get(sector.Port); + console.write(port.Name+", class "+port.Class) + } + else + console.write("None"); + console.crlf(); + console.attributes="HB"; + if(sector.Planet) { + var planet=planets.Get(sector.Planet); + console.writeln("Planet "+planet.Name); + } + console.attributes="HC"; + console.writeln("Other Ships"); + console.attributes="C"; + for(i=1;i<players.length;i++) { + var otherloc=playerLocation.Get(i); + + if(otherloc.Sector==secnum) { + var otherplayer=players.Get(i); + + if(otherplayer.UserNumber > 0 && otherplayer.Sector==secnum) { + if(otherplayer.Record==player.Record) + continue; + if(otherplayer.KilledBy!=0) + continue; + + count++; + console.crlf(); + console.write(" "+otherplayer.Alias); + if(otherplayer.TeamNumber>0) + console.write(" Team ["+otherplayer.TeamNumber+"]"); + console.write(" with "+otherplayer.Fighters+" fighters"); + if(otherplayer.Landed) + console.write(" (on planet)"); + else if(otherplayer.Ported) + console.write(" (docked)"); + else if(otherplayer.Online) + console.write(" (online)"); + } + } + } + if(count==0) + console.write(" None"); + console.crlf(); + console.attributes="HG"; + console.writeln("Fighters defending sector"); + console.attributes="G"; + if(sector.Fighters==0) + console.writeln(" None"); + else { + console.write(" "+sector.Fighters); + if(sector.FighterOwner<0) + console.writeln(" (Cabal)"); + else if(sector.FighterOwner==player.Record) + console.writeln(" (yours)"); + else { + var otherplayer=players.Get(sector.FighterOwner); + console.write(" (belong to "+otherplayer.Alias); + if(otherplayer.TeamNumber) + console.write(" Team ["+otherplayer.TeamNumber+"]") + console.writeln(")"); + } + } + console.attributes="HW"; + console.write("Warps lead to "); + count=0; + for(i=0; i<sector.Warps.length; i++) { + if(sector.Warps[i] != 0) { + if(count) + console.write(", "); + console.write(sector.Warps[i]); + count++; + } + } + console.attributes="W"; + console.crlf(); +} + +function ShortestPath(start, end) +{ + var i,j; + var hops=0; + var univ=new Array(sectors.length); + var done=false; + var ret=new Array(); + + function MarkWarps(univ, pos, end, hops) + { + var i; + + for(i=0; i<univ[pos].Warps.length; i++) { + if(univ[pos].Warps[i]==0) + continue; + if(univ[univ[pos].Warps[i]]==undefined) { + univ[univ[pos].Warps[i]]=sectors.Get(univ[pos].Warps[i]); + univ[univ[pos].Warps[i]].hops=hops; + if(univ[pos].Warps[i]==end) + return(true); + } + } + return(false); + } + + /* Do the expansion */ + univ[start]=sectors.Get(start); + univ[start].hops=hops; + while(!done) { + for(i=1; i<sectors.length; i++) { + if(univ[i]!=undefined && univ[i].hops==hops) { + if(MarkWarps(univ, i, end, hops+1)) { + done=true; + break; + } + } + } + hops++; + } + ret.push(end); + for(i=end;i!=start;) { + var lasthop=i; + for(j=0; j<univ[i].Warps.length; j++) { + if(univ[univ[i].Warps[j]]!=undefined && univ[univ[i].Warps[j]].hops<univ[i].hops) { + i=univ[i].Warps[j]; + if(i!=start) + ret.unshift(i); + break; + } + } + if(i==lasthop) + return(null); + } + return(ret); +} + diff --git a/xtrn/tw2/structs.js b/xtrn/tw2/structs.js deleted file mode 100644 index d4f86e7314c72c134b869eb83105959554d6f028..0000000000000000000000000000000000000000 --- a/xtrn/tw2/structs.js +++ /dev/null @@ -1,326 +0,0 @@ -var PlayerProperties=[ - { - prop:"UserNumber" - ,name:"User Number" - ,type:"Integer" - ,def:(user == undefined?0:user.number) - } - ,{ - prop:"Points" - ,name:"Pointes" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"Alias" - ,name:"Alias" - ,type:"String:42" - ,def:(user == undefined?"":user.alias) - } - ,{ - prop:"LastOnDay" - ,name:"Date Last On" - ,type:"Date" - ,def:system.datestr() - } - ,{ - prop:"KilledBy" - ,name:"Killed By" - ,type:"SignedInteger" - ,def:0 - } - ,{ - prop:"TurnsLeft" - ,name:"Turns Remaining" - ,type:"Integer" - ,def:Settings.TurnsPerDay - } - ,{ - prop:"Sector" - ,name:"Sector" - ,type:"Integer" - ,def:1 - } - ,{ - prop:"Fighters" - ,name:"Fighters" - ,type:"Integer" - ,def:Settings.StartingFighters - } - ,{ - prop:"Holds" - ,name:"Holds" - ,type:"Integer" - ,def:Settings.StartingHolds - } - ,{ - prop:"Commodities" - ,name:"Commodities" - ,type:"Array:3:Integer" - ,def:[0,0,0] - } - ,{ - prop:"Credits" - ,name:"Credits" - ,type:"Integer" - ,def:Settings.StartingCredits - } - ,{ - prop:"TeamNumber" - ,name:"Team Number" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"LastIn" - ,name:"Sector Last In" - ,type:"Integer" - ,def:1 - } - ,{ - prop:"Online" - ,name:"Online" - ,type:"Boolean" - ,def:false - } - ,{ - prop:"Ported" - ,name:"Ported" - ,type:"Boolean" - ,def:false - } - ,{ - prop:"Landed" - ,name:"Landed" - ,type:"Boolean" - ,def:false - } - ]; - -var PlayerLocation = [ - { - prop:"Sector" - ,name:"Sector" - ,type:"Integer" - ,def:1 - } - ]; - -var SectorProperties = [ - { - prop:"Warps" - ,name:"Warps" - ,type:"Array:6:Integer" - ,def:[0,0,0,0,0,0] - } - ,{ - prop:"Port" - ,name:"Port" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"Planet" - ,name:"Planet" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"Fighters" - ,name:"Fighters" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"FighterOwner" - ,name:"Fighters Owner" - ,type:"SignedInteger" - ,def:0 - } - ]; - -var PortProperties = [ - { - prop:"Name" - ,name:"Name" - ,type:"String:42" - ,def:"" - } - ,{ - prop:"Class" - ,name:"Class" - ,type:"Integer" - ,def:"" - } - ,{ - prop:"Commodities" - ,name:"Commodities" - ,type:"Array:3:Float" - ,def:[0,0,0] - } - ,{ - prop:"Production" - ,name:"Production (units/day)" - ,type:"Array:3:SignedInteger" - ,def:[0,0,0] - } - ,{ - prop:"PriceVariance" - ,name:"Price Variance (percentage)" - ,type:"Array:3:SignedInteger" - ,def:[0,0,0] - } - ,{ - prop:"LastUpdate" - ,name:"Port last produced" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"OccupiedBy" - ,name:"Occupied By" - ,type:"Integer" - ,def:0 - } - ]; - -var PlanetProperties = [ - { - prop:"Name" - ,name:"Name" - ,type:"String:42" - ,def:"" - } - ,{ - prop:"Created" - ,name:"Planet has been created" - ,type:"Boolean" - ,def:false - } - ,{ - prop:"Commodities" - ,name:"Commodities" - ,type:"Array:3:Float" - ,def:[0,0,0] - } - ,{ - prop:"Production" - ,name:"Production (units/day)" - ,type:"Array:3:SignedInteger" - ,def:[0,0,0] - } - ,{ - prop:"LastUpdate" - ,name:"Planet last produced" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"Sector" - ,name:"Location of planet" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"OccupiedBy" - ,name:"Occupied By" - ,type:"Integer" - ,def:0 - } - ]; - -var PlayerMessageProperties = [ - { - prop:"Read" - ,name:"Message has been read" - ,type:"Boolean" - ,def:true - } - ,{ - prop:"To" - ,name:"Player the message is to" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"From" - ,name:"Player the message is from" - ,type:"SignedInteger" - ,def:0 - } - ,{ - prop:"Destroyed" - ,name:"Number of Fighters Destroyed" - ,type:"Integer" - ,def:0 - } - ]; - -var RadioMessageProperties = [ - { - prop:"Read" - ,name:"Message has been read" - ,type:"Boolean" - ,def:false - } - ,{ - prop:"To" - ,name:"Player the message is to" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"From" - ,name:"Player the message is from" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"Message" - ,name:"Test of the message" - ,type:"String:74" - ,def:"" - } - ]; - -var TeamProperties = [ - { - prop:"Password" - ,name:"Team Password" - ,type:"String:4" - ,def:"" - } - ,{ - prop:"Members" - ,name:"Team Members" - ,type:"Array:4:Integer" - ,def:[0,0,0,0] - } - ,{ - prop:"Size" - ,name:"Number of members" - ,type:"Integer" - ,def:0 - } - ]; - -var CabalProperties = [ - { - prop:"Sector" - ,name:"Sector" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"Size" - ,name:"Size" - ,type:"Integer" - ,def:0 - } - ,{ - prop:"Goal" - ,name:"Goal" - ,type:"Integer" - ,def:0 - } - ]; diff --git a/xtrn/tw2/teams.js b/xtrn/tw2/teams.js new file mode 100644 index 0000000000000000000000000000000000000000..bede88fa820e50059945883b86bb1859b349151e --- /dev/null +++ b/xtrn/tw2/teams.js @@ -0,0 +1,275 @@ +var TeamProperties = [ + { + prop:"Password" + ,name:"Team Password" + ,type:"String:4" + ,def:"" + } + ,{ + prop:"Members" + ,name:"Team Members" + ,type:"Array:4:Integer" + ,def:[0,0,0,0] + } + ,{ + prop:"Size" + ,name:"Number of members" + ,type:"Integer" + ,def:0 + } + ]; + +var teams=new RecordFile(fname("teams.dat"), TeamProperties); + +function TeamMenu() +{ + function TeamHelp() { + console.crlf(); + if(player.TeamNumber > 0) + console.printfile(fname("team-member.asc")); + else + console.printfile(fname("team-none.asc")); + } + + TeamHelp(); + + while(1) { + var values=new Array(); + if(player.TeamNumber > 0) + values=['1','2','3','4','5','6','7','?']; + else + values=['1','2','3','?']; + console.crlf(); + console.attributes="W"; + console.write("Team Command (?=help)? "); + switch(InputFunc(values)) { + case '?': + TeamHelp(); + break; + case '1': + return; + case '2': + CreateTeam(); + break; + case '3': + JoinTeam(); + break; + case '4': + QuitTeam(); + break; + case '5': + TeamTransfer("Credits"); + break; + case '6': + TeamTransfer("Fighters"); + break; + case '7': + LocateTeam(); + break; + } + } +} + +function LocateTeam() +{ + console.writeln("Locating Other Team members."); + console.crlf(); + console.writeln("Name Sector"); + console.writeln("==================== ======"); + var count=0; + var i; + for(i=1;i<players.length; i++) { + otherplayer=players.Get(i); + if(otherplayer.Record!=player.Record + && otherplayer.UserNumber!=0 + && otherplayer.TeamNumber==player.TeamNumber) { + count++; + } + console.write(format("%-41s ",otherplayer.Alias)); + if(otherplayer.KilledBy != 0) + console.write(" Dead!"); + else + console.write(otherplayer.Sector); + console.crlf(); + } + console.crlf(); + if(count==0) + console.writeln("None Found"); +} + +function CreateTeam() +{ + if(player.TeamNumber > 0) { + console.writeln("You already belong to a Team! "); + console.writeln("You must quit a team to form another Team."); + return(false); + } + var password=''; + while(password.length != 4) { + console.writeln("To form a Team you will need to input a 4 character Team Password"); + console.write("Enter Password [ENTER]=quit? "); + password=console.getstr(4); + if(password=='') + return(false); + if(password.length != 4) + console.writeln("Password MUST be 4 characters"); + } + console.crlf(); + console.writeln("REMEMBER YOUR TEAM PASSWORD!"); + var team=null; + for(i=1; i<teams.length; i++) { + team=teams.Get(i); + if(team.Size > 0) + break; + team=null; + } + if(team==null) + team=teams.New(); + team.Password=password; + team.Size=1; + team.Members[0]=player.Record; + player.TeamNumber=team.Record; + team.Put(); + player.Put(); + console.attributes="HYI"; + twmsg.writeln(player.Alias+" Created Team "+team.Record+" the " /* TNAM$ */); + console.writeln("Team number [" + team.Record + "] CREATED!"); + console.attributes="HK"; + return(true); +} + +function JoinTeam() +{ + if(player.TeamNumber > 0) { + console.writeln("You already belong to a Team! "); + console.writeln("You must quit one team to join another Team."); + return(false); + } + + console.write("What Team number do you wish to join (0=quit)? "); + var tnum=console.getnum(teams.length-1); + if(!(tnum > 0 && tnum < teams.length)) + return(false); + + var team=teams.Get(tnum); + if(team.Size > 3) { + console.writeln("The Team you picked has a maximum amount of members!"); + return(false); + } + console.write("Please enter Password to Join Team #"+team.Record+" ? "); + var pass=console.getstr(4); + if(pass != team.Password) { + console.writeln("Invalid Password entered!"); + return(false); + } + var i; + for(i=0; i<team.Members.length; i++) { + if(team.Members[i]==0) { + team.Members[i]=player.Record; + team.Size++; + player.TeamNumber=team.Record; + team.Put(); + player.Put(); + twmsg.writeln(player.Alias + " Joined Team "+team.Record); + console.attributes="HC"; + console.writeln("Your Team info has been recorded! Have fun!"); + console.attributes="HK"; + return(true); + } + } + console.attributes="HR"; + console.writeln("Corrupt team detected on join! Please notify the Sysop!"); + twmsg.writeln("!!! Team "+team.Record+" is corrupted (join)!"); + return(false); +} + +function QuitTeam() +{ + if(player.TeamNumber != 0) { + console.writeln("You don't belong to a Team!"); + return(false); + } + console.write("Are you sure you wish to quit your Team [N]? "); + if(GetKeyEcho()=='Y') { + var team=teams.Get(player.TeamNumber); + player.TeamNumber=0; + var i; + for(i=0; i<team.Members.length; i++) { + if(team.Members[i]==player.Record) { + team.Members[i]=0; + team.Size--; + player.Put(); + team.Put(); + console.crlf(); + console.attributes="HG"; + console.writeln("You have been removed from Team play"); + console.attributes="HK"; + return(true); + } + } + } + console.attributes="HR"; + console.writeln("Corrupt team detected on quit! Please notify the Sysop!"); + twmsg.writeln("!!! Team "+team.Record+" is corrupted (quit)!"); + return(false); +} + +function TeamTransfer(type) +{ + console.write("Transfer "+type+" to another Team member [N]? "); + if(GetKeyEcho()!='Y') + return(false); + if(player[type] < 1) { + console.writeln("You don't have any "+type+"."); + return(false); + } + var i; + + var otherplayer=null; + for(i=1;i<players.length; i++) { + var otherloc=playerLocation.Get(i); + if(otherloc.Sector==player.Sector) { + otherplayer=players.Get(i); + if(otherplayer.Sector==player.Sector + && otherplayer.Record!=player.Record + && otherplayer.KilledBy!=0 + && otherplayer.UserNumber!=0 + && otherplayer.TeamNumber==player.TeamNumber) { + console.write("Transfer "+type+" to " + otherplayer.Alias + " (Y/[N])? "); + if(GetKeyEcho()=='Y') + break; + } + otherplayer=null; + } + } + if(otherplayer==null) { + console.writeln("There is no one else in this sector"); + return(false); + } + while(1) { + console.writeln("You have" + player[type] + " "+type.toLowercase()+"."); + console.writeln(otherplayer.Alias + " has" + otherplayer[type] + " "+type.toLowercase()+"."); + console.write("How many "+type+" do you wish to Transfer? "); + var transfer=console.getnum(player[type]); + if(transfer<1 || transfer > player[type]) + return(false); + if(type=="Credits") { + if(otherplayer.Credits + transfer > 25000) { + console.writeln("You Team mate will have more than 25,000 credits"); + console.write("Do you wish to complete the Transfer [N]? "); + if(GetKeyEcho()!='Y') + return(false); + } + } + else if(type=="Fighters") { + if(otherplayer.Fighters + transfer > 9999) + console.writeln("Maximum amount of fighters per player is 9999"); + } + } + otherplayer[type] += transfer; + player[type] -= transfer; + player.Put(); + otherplayer.Put(); + console.writeln(type+" Transfered!"); + return(true); +} diff --git a/xtrn/tw2/tw2.js b/xtrn/tw2/tw2.js index 1d92b81b2746bdad94b5a0cb6c72bd586d2bedb3..078d47010031dbbbf38ae416cb5e796b2dd9ebf2 100644 --- a/xtrn/tw2/tw2.js +++ b/xtrn/tw2/tw2.js @@ -3,14 +3,6 @@ try { throw new Error() } catch(e) { startup_path=e.fileName } startup_path=startup_path.replace(/[\/\\][^\/\\]*$/,''); startup_path=backslash(startup_path); -load("recordfile.js"); -load("lockfile.js"); -load(startup_path+"filename.js"); -load(fname("gamesettings.js")); -var Settings=new GameSettings(); - -load(fname("structs.js")); - var on_at=time(); var i; @@ -35,51 +27,34 @@ var Commodities=[ } ]; -var sectors=new RecordFile(fname("sectors.dat"), SectorProperties); -var ports=new RecordFile(fname("ports.dat"), PortProperties); -var players=new RecordFile(fname("players.dat"), PlayerProperties); -var playerLocation=new RecordFile(fname("player-loc.dat"), PlayerLocation); -var teams=new RecordFile(fname("teams.dat"), TeamProperties); -var planets=new RecordFile(fname("planets.dat"), PlanetProperties); +load("recordfile.js"); +load("lockfile.js"); +load(startup_path+"filename.js"); +load(fname("gamesettings.js")); +var Settings=new GameSettings(); + +load(fname("structs.js")); +load(fname("ports.js")); +load(fname("planets.js")); +load(fname("teams.js")); +load(fname("sectors.js")); +load(fname("maint.js")); +load(fname("players.js")); +load(fname("messages.js")); +load(fname("computer.js")); +load(fname("input.js")); + var twmsg=new File(fname("twmesg.dat")); var twopeng=new File(fname("twopeng.dat")); twopeng.open("a", true); twmsg.open("a", true); -var twpmsg=new RecordFile(fname("twpmesg.dat"), PlayerMessageProperties); -var twrmsg=new RecordFile(fname("twrmesg.dat"), RadioMessageProperties); -var cabals=new RecordFile(fname("cabal.dat"), CabalProperties); var today=system.datestr(system.datestr()); js.on_exit("do_exit()"); /* Run maintenance */ if(Settings.MaintLastRan != system.datestr()) { - Settings.MaintLastRan = system.datestr(); - Settings.save(); - console.attributes="Y"; - console.writeln("Running maintence program..."); - console.crlf(); - console.crlf(); - console.writeln("Trade Wars maintence program"); - console.writeln(" by Chris Sherrick (PTL)"); - console.crlf(); - console.writeln("This program is run once per day."); - twmsg.writeln(system.timestr()+": "+user.alias+": Maintence program ran"); - console.writeln("Deleting inactive players"); - - var oldest_allowed=today-Settings.DaysInactivity*86400; - for(i=1; i<players.length; i++) { - var p=players.Get(i); - if(p.UserNumber > 0) { - if((!file_exists(system.data_dir+format("user/%04d.tw2",p.UserNumber))) || (system.datestr(p.LastOnDay) < oldest_allowed && p.KilledBy != 0)) { - DeletePlayer(p) - } - } - } - console.crlf(); - MoveCabal(); - - RankPlayers(); + RunMaint(); } console.attributes="C"; @@ -100,146 +75,9 @@ console.crlf(); console.attributes="W"; console.writeln("Initializing..."); console.writeln("Searching my records for your name."); -var player; -var firstnew; -for(i=1; i<players.length; i++) { - player=players.Get(i); - if(player.UserNumber == user.number && (!file_exists(system.data_dir+format("user/%04d.tw2",player.UserNumber)))) - DeletePlayer(player); - if(player.UserNumber==0 && firstnew==undefined) - firstnew=player; - if(player.UserNumber == user.number) - break; -} -if(player==undefined || player.UserNumber!=user.number) { - console.attributes="G"; - console.writeln("I can't find your record, so I am assuming you are a new player."); - console.attributes="M"; - console.writeln("Entering a new player..."); - player=firstnew; - if(player==undefined) { - console.writeln("I'm sorry but the game is full."); - console.writeln("Please leave a message for the Sysop so"); - console.writeln("he can save a space for you when one opens up."); - twmsg.writeln(system.timestr()+": New player not allowed - game full."); - exit(0); - } - console.crlf(); - console.writeln("Notice: If you don't play this game for "+Settings.DaysInactivity+" days, you will"); - console.writeln("be deleted to make room for someone else."); - console.crlf(); - console.writeln("Your ship is being initialized."); - - /* Lock the player file and mark us online... */ - if(!Lock(players.file.name, bbs.node_num, true, 10)) { - console.writeln("!!!Unable to lock player data!"); - twmsg.writeln("!!!Unable to lock player data!"); - exit(1); - } - player.ReInit(); - player.Online=true; - player.Put(); - Unlock(players.file.name); - - twmsg.writeln(system.timestr()+" "+user.alias+": New Player logged on"); - Instructions(); -} -else { - /* Lock the player file and mark us online... */ - if(!Lock(players.file.name, bbs.node_num, true, 10)) { - console.writeln("!!!Unable to lock player data!"); - twmsg.writeln("!!!Unable to lock player data!"); - exit(1); - } - player.Online=true; - player.Put(); - Unlock(players.file.name); - - console.crlf(); /* TODO: BASIC magic... N$ appears empty tw2.bas: 242 */ - twmsg.writeln(system.timestr()+" "+user.alias+": Logged on"); - if(today < system.datestr(player.LastOnDay)) { - console.writeln("I'm sorry, but you won't be allowed on for another " + parseInt((system.datestr(player.LastOnDay)-today)/86400) + " day(s)"); - exit(0); - } - if(today==system.datestr(player.LastOnDay)) { - if(player.KilledBy != -99) { - console.writeln("You have been on today."); - if(player.TurnsLeft<1) { - console.writeln("You don't have any turns left today. You will be allowed to play tomorrow."); - exit(0); - } - if(player.KilledBy==player.Record) { - console.writeln("You killed yourself today. You will be allowed to play tomorrow."); - exit(0); - } - console.writeln("The following happened to your ship since your last time on:"); - var count=0; - for(i=0; i<twpmsg.length; i++) { - var msg=twpmsg.Get(i); - - if(msg.To==player.Record && !msg.Read) { - count++; - if(msg.From==-98) - console.writeln("A deleted player destroyed "+msg.Destroyed+" fighters."); - else if(msg.From==-1) { - console.attributes="R"; - console.writeln("The Cabal destroyed "+msg.Destroyed+" fighters."); - } - else { - var otherplayer=players.Get(msg.From); - - console.writeln(otherplayer.Alias+" "+(otherplayer.TeamNumber?" Team["+otherplayer.TeamNumber+"] ":"")+"destroyed "+msg.Destroyed+" of your fighters."); - } - msg.Read=true; - msg.Put(); - } - } - if(count==0) - console.writeln("Nothing"); - } - } - else { - player.TurnsLeft=Settings.TurnsPerDay; - } - player.LastOnDay=system.datestr(); - if(player.KilledBy != 0) { - switch(player.KilledBy) { - case player.Record: - console.attributes="R"; - console.writeln("You managed to kill yourself on your last time on."); - break; - case -1: - console.attributes="R"; - console.writeln("You have been killed by the Cabal!"); - break; - case -98: - console.writeln("You have been killed by a deleted player."); - break; - default: - var otherplayer=players.Get(player.KilledBy); - - console.writeln(otherplayer.Alias+" destroyed your ship!"); - break; - } - player.ReInit(); - } -} -file_touch(system.data_dir+format("user/%04d.tw2",player.UserNumber)) -ReadRadio(); -if(player.Sector < 1 || player.Sector >= sectors.length) { - console.writeln("You are being moved to sector 1"); - player.Sector=1; -} -location=playerLocation.Get(player.Record); -location.Sector=player.Sector; -location.Put(); - -if(player.Credits > 25000) { - console.crlf(); - console.writeln("Tax time! You are being taxed 5000 credits to help support the resistance"); - console.writeln("against the evil Cabal."); - player.Credits -= 5000; -} +var player=null; +if(!LoadPlayer()) + exit(0); var exit_tw2=false; @@ -272,208 +110,12 @@ function Menu() case 'A': /* 25000 */ console.writeln("<Attack>"); - var count=0; - var i; - - if(player.Fighters < 1) { - console.writeln("You don't have any fighters."); - break; - } - for(i=1;i<players.length; i++) { - var otherloc=playerLocation.Get(i); - if(otherloc.Sector==player.Sector) { - var otherplayer=players.Get(i); - if(otherplayer.Sector==player.Sector - && otherplayer.Record!=player.Record - && otherplayer.KilledBy!=0 - && otherplayer.UserNumber!=0 - && !otherplayer.Online) { - count++; - console.write("Attack "+otherplayer.Alias+" (Y/N)[Y]? "); - if(GetKeyEcho()!='N') { - console.writeln("<Yes>"); - break; - } - } - } - otherplayer=null; - } - if(otherplayer!=null) { - DoBattle(otherplayer, otherplayer.TeamNumber > 0); - if(otherplayer.Fighters==0) { - KilledBy(otherplayer, player, true); - /* 15600 player salvages ship from otherplayer */ - var salvaged=parseInt(otherplayer.Holds/4)+1; - if(player.Holds + salvaged > 50) - salvaged=50-player.Holds; - if(salvaged < 1) - console.writeln("You destroyed the ship, but you can't salvage anything from it"); - else { - var j; - - console.writeln("You destroyed the ship and salvaged these cargo holds:"); - var holds=new Array(Commodities.length+1); - for(i=0; i<holds.length+1; i++) - holds[i]=0; - for(i=0; i<otherplayer.Holds; i++) { - var limit=0; - var r=random(otherplayer.Holds)+1; - for(j=0; j<Commodities.length; j++) { - limit += otherplayer.Commodities[j]; - if(r<limit) { - otherplayer.Commodities[j]--; - holds[j]++; - r=0; - break; - } - } - if(r==0) - holds[Commodities.length]++; - } - if(holds[Commodities.length]>0) { - console.writeln(" "+holds[Commodities.length]+" empty."); - player.Holds+=holds[Commodities.length]; - } - for(j=0; j<Commodities.length; j++) { - if(holds[j]>0) { - console.writeln(" "+holds[j]+" with "+Commodities[j].name.toLowerCase()+"."); - player.Holds+=holds[j]; - player.Commodities[j]+=holds[j]; - } - } - } - } - } - else { - if(count) - console.writeln("There are no other ships in here"); - else - console.writeln("There are no ships here to attack."); - } + AttackPlayer(); break; case 'C': /* 33640 */ console.writeln("<Computer>"); - console.crlf(); - console.attributes="HW"; - console.writeln("<Computer activated>"); - var showhelp=true; - var exitcomputer=false; - while(!exitcomputer) { - if(showhelp) { - console.crlf(); - console.printfile(fname("computer.asc")); - } - console.attributes="HW"; - console.write("Computer command (?=help)? "); - switch(InputFunc(['?','1','2','3','4','5'])) { - case '?': - showhelp=true; - break; - case '1': - /* 33990 */ - console.crlf(); - console.attributes="Y"; - console.writeln("<Computer deactivated>"); - exitcomputer=true; - break; - case '2': - /* 33780 */ - console.write("What sector number is the port in? "); - var sec=console.getnum(sectors.length-1); - if(sec > 0 && sec < sectors.length) { - var sector=sectors.Get(sec); - if(sector.Port==0 || (sector.Fighters>0 && sector.Fighters!=player.Record)) { - console.crlf(); - console.writeln("I have no information about that port."); - break; - } - if(sec==1) { - SolReport(); - } - else { - PortReport(sector); - } - } - break; - case '3': - /* 33830 */ - console.write("What sector do you want to get to? "); - var sec=console.getnum(sectors.length-1); - if(sec > 0 && sec < sectors.length) { - if(sec==player.Sector) { - console.writeln("You are in that sector."); - break; - } - console.crlf(); - console.writeln("Computing shortest path."); - var path=ShortestPath(player.Sector, sec); - if(path==null) { - console.writeln("There was an error in computation between sectors."); - } - else { - console.writeln("The shortest path from sector "+player.Sector+" to sector "+sec+" is:"); - var i; - for(i in path) { - if(i!=0) - console.write(" - "); - console.write(path[i]); - } - } - } - break; - case '4': - /* 33900 */ - console.crlf(); - console.write("Ranking Players."); - var ranked=RankPlayers(); - console.crlf(); - - console.attributes="W"; - console.writeln("Player Rankings: "+system.timestr()); - console.writeln("Rank Value Team Player"); - console.writeln("==== ============= ====== ======") - for(rank in ranked) { - var p=players.Get(ranked[rank].Record); - console.writeln(format("%4d %13d %-6s %s" - ,rank+1 - ,ranked[rank].Score - ,p.TeamNumber==0?"":format(" %-2d " - ,p.TeamNumber),p.Alias)); - } - break; - case '5': - /* 33960 */ - console.crlf(); - console.writeln("Warming up sub-space radio."); - mswait(500); - console.crlf(); - console.write("Who do you wish to send this message to (search string)? "); - var sendto=console.getstr(42); - var p=MatchPlayer(sendto); - if(p==null) - break; - console.writeln("Tuning in to " + p.Alias + "'s frequency."); - console.crlf(); - console.writeln("Due to the distances involved, messages are limited to 74 chars."); - console.writeln("Pressing [ENTER] with no input quits"); - console.writeln(" [------------------------------------------------------------------------]"); - console.attributes="HY"; - console.write("? "); - console.attributes="W"; - var msg=console.getstr(74); - if(msg==null) - break; - msg=msg.replace(/\s*$/,''); - if(msg=='') - break; - RadioMessage(player.Record, p.Record, msg); - break; - default: - console.crlf(); - console.writeln("Invalid command. Enter ? for help"); - } - } + ComputerMenu(); break; case 'D': console.writeln("<Display>"); @@ -494,59 +136,12 @@ function Menu() case 'F': /* 24000 */ console.writeln("<Drop/Take Fighters>"); - if(player.Sector < 8) { - console.writeln("You can't leave fighters in the Union (sectors 1-7)"); - break; - } - var sector=sectors.Get(player.Sector); - if(sector.Fighters > 0 && sector.FighterOwner != player.Record) { - console.writeln("There are already fighters in this sector!"); - break; - } - console.writeln("You have " + (player.Fighters+sector.Fighters) + " fighters available."); - console.write("How many fighters do you want defending this sector? "); - var newf=player.Fighters+sector.Fighters; - if(newf > 9999) - newf=9999; - var newf=console.getnum(newf); - if(newf >= 0 && newf <=player.Fighters+sector.Fighters) { - if((player.Fighters+sector.Fighters)-newf > 9999) { - console.writeln("Too many ships in your fleet! You are limited to 9999"); - break; - } - player.Fighters=(player.Fighters+sector.Fighters)-newf; - sector.Fighters=newf; - if(sector.Fighters > 0) - sector.FighterOwner=player.Record; - sector.Put(); - player.Put(); - console.writeln("Done. You have " + player.Fighters + " fighter(s) in your fleet."); - } + DropFighters(); break; case 'G': /* 27500 */ console.writeln("<Gamble>"); - console.attributes="HW"; - console.writeln("You have "+player.Credits+" credits."); - console.writeln("How much do you want to gamble at double or nothing (50-50 odds)"); - console.write("[0]? "); - var gamble=console.getnum(player.Credits > 99999?99999:player.Credits); - if(gamble > 0 && gamble <=player.Credits) { - console.write("Flipping the coin..."); - mswait(250); - if(random(2)==1) { - console.crlf(); - player.Credits-=gamble; - console.writeln("Sorry, you lost."); - } - else { - console.crlf(); - player.Credits+=gamble; - console.writeln("You won!"); - } - player.Put(); - console.writeln("You now have "+player.Credits+" credits."); - } + PlayerGamble(); break; case 'I': console.writeln("<Info>"); @@ -555,200 +150,17 @@ function Menu() case 'L': /* 31000 */ console.writeln("<Land/Create planet>"); - console.crlf(); - console.attributes="HY"; - console.writeln("Landing..."); - var sector=sectors.Get(player.Sector); - var planet=null; - if(sector.Planet==0) { - /* TODO: Race condition? */ - CreatePlanet(sector); - } - else { - /* 32310 */ - /* Lock the planet file and ensure we can land... */ - if(!Lock(planets.file.name, bbs.node_num, true, 5)) { - console.writeln("The spaceport is busy. Try again later."); - break; - } - planet=planets.Get(sector.Planet); - if(planet.OccupiedBy != 0) { - console.writeln("The spaceport is busy. Try again later."); - Unlock(planets.file.name); - break; - } - planet.OccupiedBy=player.Record; - planet.Put(); - Unlock(ports.file.name); - player.Landed=true; - player.Put(); - - Production(planet); - PlanetReport(planet); - console.attributes="HW"; - PlanetMenu(planet); - - if(!Lock(planets.file.name, bbs.node_num, true, 10)) - twmsg.writeln("!!! Error locking ports file!"); - planet.OccupiedBy=0; - planet.Put(); - Unlock(planets.file.name); - player.Landed=false; - player.Put(); - } + LandOnPlanet(); break; case 'M': /* 23000 */ console.writeln("<Move>"); - if(player.TurnsLeft < 1) { - console.writeln("I'm sorry but you don't have any turns left."); - break; - } - console.attributes="HW"; - console.write("Warps lead to: "); - var sector=sectors.Get(player.Sector); - var i; - var count=0; - for(i=0; i<sector.Warps.length; i++) { - if(sector.Warps[i]>0) { - if(count>0) - console.write(", "); - console.write(sector.Warps[i]); - count++; - } - } - console.crlf(); - console.write("To which sector? "); - var to=console.getnum(sectors.length-1); - if(MoveTo(to)) + if(PlayerMove()) return; break; case 'P': console.writeln("<Port>"); - console.attributes="HR"; - console.crlf(); - console.writeln("Docking..."); - if(player.TurnsLeft<1) { - console.writeln("Sorry, but you don't have any turns left."); - break; - } - var sector=sectors.Get(player.Sector); - if(sector.Port<1) { - console.writeln("There are no ports in this sector."); - break; - } - player.TurnsLeft--; - player.Ported=true; - player.Put(); - console.writeln("One turn deducted"); - if(player.Sector==1) { - /* 33200 */ - var prices=SolReport(); - console.attributes="HR"; - console.writeln("You have " + player.Credits + " credits."); - console.crlf(); - /* Holds */ - var maxbuy=parseInt(player.Credits/prices[0]); - if(player.Holds+maxbuy>50) - maxbuy=50-player.Holds; - if(maxbuy > 0) { - console.write("How many holds do you want to buy [0]? "); - var buy=console.getnum(maxbuy); - if(buy>0) { - player.Holds+=buy; - player.Credits -= buy*prices[0]; - player.Put(); - console.writeln("You have " + player.Credits + " credits."); - } - } - /* Fighters */ - var maxbuy=parseInt(player.Credits/prices[1]); - if(player.Fighters+maxbuy>9999) - maxbuy=9999-player.Fighters; - if(maxbuy > 0) { - console.write("How many fighters do you want to buy [0]? "); - var buy=console.getnum(maxbuy); - if(buy>0) { - player.Fighters+=buy; - player.Credits -= buy*prices[1]; - player.Put(); - console.writeln("You have " + player.Credits + " credits."); - } - } - /* Turns */ - var maxbuy=parseInt(player.Credits/prices[2]); - if(maxbuy > 0) { - console.write("How many turns do you want to buy [0]? "); - var buy=console.getnum(maxbuy); - if(buy>0) { - player.TurnsLeft+=buy; - player.Credits -= buy*prices[2]; - player.Put(); - console.writeln("You have " + player.Credits + " credits."); - } - } - } - else { - var sector=sectors.Get(player.Sector); - - /* Lock the port file and ensure we can dock... */ - if(!Lock(ports.file.name, bbs.node_num, true, 5)) { - console.writeln("The port is busy. Try again later."); - break; - } - var port=ports.Get(sector.Port); - if(port.OccupiedBy != 0) { - console.writeln("The port is busy. Try again later."); - Unlock(ports.file.name); - break; - } - port.OccupiedBy=player.Record; - port.Put(); - Unlock(ports.file.name); - Production(port); - var sale=PortReport(sector); - console.attributes="HR"; - var count=0; - - console.writeln(); - - console.attributes="HY"; - /* Sell... */ - for(i=0; i<Commodities.length; i++) { - if(sale[i].Vary < 0) { - var amount=Transact(i, sale[i].Price, sale[i].Vary, sale[i].Number); - if(amount >= 0) { - count++; - port.Commodities[i] += amount; - port.Put(); - } - } - } - /* Buy... */ - for(i=0; i<Commodities.length; i++) { - if(sale[i].Vary > 0) { - var amount=Transact(i, sale[i].Price, sale[i].Vary, sale[i].Number); - if(amount >= 0) { - count++; - port.Commodities[i] -= amount; - port.Put(); - } - } - } - if(count==0) { - console.attributes="IC"; - console.writeln("You don't have anything they want, and they don't have anything you can buy"); - console.attributes="C"; - } - - if(!Lock(ports.file.name, bbs.node_num, true, 10)) - twmsg.writeln("!!! Error locking ports file!"); - port.OccupiedBy=0; - port.Put(); - Unlock(ports.file.name); - } - player.Ported=false; - player.Put(); + DockAtPort(); break; case 'T': /* 32799 */ @@ -787,360 +199,6 @@ function Menu() } } -function CheckSector() -{ - if(player.Sector==85) { - console.crlf(); - console.attributes="W"; - console.writeln("Congratulations! You've defeated the cabal and gained 100,000 points!"); - player.Points += 100000; - player.Put(); - console.writeln("Unfortunately, victory is fleeting..."); - - var sector=sectors.Get(85); - sector.Fighters=3000; - sector.FighterOwner=-1; - sector.Put(); - twopeng.writeln("Congratulations go to "+player.Alias+ - " who invaded the Cabal empire on " + system.datestr() + - " and received 100,000 points!"); - return(false); - } - return(true); -} - -function EnterSector() /* 20000 */ -{ - var sector=sectors.Get(player.Sector); - var fighterteam=-1; - - console.attributes="Y"; - DisplaySector(sector.Record); - if(sector.FighterOwner > 0) { - var otherplayer=players.Get(sector.FighterOwner); - if(otherplayer.TeamNumber > 0) - fighterteam=otherplayer.TeamNumber; - } - while(sector.FighterOwner != player.Record && sector.Fighters > 0 && fighterteam != player.TeamNumber) { - console.writeln("You have to destroy the fighters before you can enter this sector."); - console.writeln("Fighters: "+player.Fighters+" / "+sector.Fighters); - console.write("Option? (A,D,I,Q,R,?):? "); - switch(InputFunc(['A','D','I','Q','R','?'])) { - case 'A': - console.writeln("<Attack>"); - var otherteam=false; - - if(sector.FighterOwner > 0) { - var otherplayer=players.Get(sector.FighterOwner); - if(otherplayer.TeamNumber>0) - otherteam-true; - } - var killed=DoBattle(sector, otherteam); - if(killed > 0) { - player.Points+=k*100; - console.writeln("You just recieved "+(k*100)+" points for that."); - } - if(sector.Fighters==0) - console.writeln("You destroyed all the fighters."); - break; - case 'D': - console.writeln("<Display>"); - DisplaySector(player.Sector); - break; - case 'I': - console.writeln("<Info>"); - PlayerInfo(player.Record); - break; - case 'Q': - console.write("Are you sure (Y/N)? "); - if(console.getkeys("YN")=='Y') { - exit_tw2=true; - return(false); - } - break; - case 'R': - console.writeln("<Retreat>"); - if(player.LastIn<1 || player.LastIn>=sectors.length) - player.LastIn=random(sectors.length-1)+1; - if(player.Fighters<1) { - if(random(2)==1) { - console.writeln("You escaped!"); - player.Sector=player.LastIn; - player.Put(); - location.Sector=player.Sector; location.Put(); - return(false); - } - console.attributes="R"; - console.writeln("You didn't escape!"); - console.writeln("Your ship has been destroyed!"); - console.crlf(); - console.attributes="R"; - console.writeln("You will start over tomorrow with a new ship."); - KilledBy(player, player, true); - return(false); - } - else { - player.Fighters--; - console.writeln("You have "+player.Fighters+" fighter(s) left."); - player.Sector=player.LastIn; - player.Put(); - location.Sector=player.Sector; location.Put(); - return(false); - } - break; - case '': - console.writeln("?=<Help>"); - break; - case '?': - console.writeln("<Help>"); - console.crlf(); - console.printfile(fname("entersector.asc")); - break; - default: - console.crlf(); - console.writeln("Invalid command. ? = Help"); - } - } - return(true); -} - -function PlayerInfo(num) -{ - var p=players.Get(num); - - console.attributes="HW"; - console.write(" Pilot's Name: "+p.Alias); - if(p.PlayerNumber>0) - console.write(" Team ["+p.TeamNumber+"]"); - console.crlf(); - console.writeln(" Fighters: "+p.Fighters); - console.attributes="HG"; - console.writeln("Sector Location: "+p.Sector); - console.writeln(" Turns left: "+p.TurnsLeft); - console.writeln(" Cargo Holds: "+p.Holds); - console.attributes="HR"; - var i; - for(i=0; i<Commodities.length; i++) - console.writeln(" # with "+Commodities[i].abbr+": "+p.Commodities[i]+" "); - console.attributes="HM"; - console.writeln(" Credits: "+p.Credits); - console.writeln(" Door points: "+p.Points); -} - -function DisplaySector(secnum) -{ - var sector=sectors.Get(secnum); - var i; - var count=0; - - console.crlf(); - console.attributes="HY"; - console.writeln("Sector "+secnum); - console.attributes="HR"; - console.write("Port "); - if(sector.Port > 0) { - var port=ports.Get(sector.Port); - console.write(port.Name+", class "+port.Class) - } - else - console.write("None"); - console.crlf(); - console.attributes="HB"; - if(sector.Planet) { - var planet=planets.Get(sector.Planet); - console.writeln("Planet "+planet.Name); - } - console.attributes="HC"; - console.writeln("Other Ships"); - console.attributes="C"; - for(i=1;i<players.length;i++) { - var otherloc=playerLocation.Get(i); - - if(otherloc.Sector==secnum) { - var otherplayer=players.Get(i); - - if(otherplayer.UserNumber > 0 && otherplayer.Sector==secnum) { - if(otherplayer.Record==player.Record) - continue; - if(otherplayer.KilledBy!=0) - continue; - - count++; - console.crlf(); - console.write(" "+otherplayer.Alias); - if(otherplayer.TeamNumber>0) - console.write(" Team ["+otherplayer.TeamNumber+"]"); - console.write(" with "+otherplayer.Fighters+" fighters"); - if(otherplayer.Landed) - console.write(" (on planet)"); - else if(otherplayer.Ported) - console.write(" (docked)"); - else if(otherplayer.Online) - console.write(" (online)"); - } - } - } - if(count==0) - console.write(" None"); - console.crlf(); - console.attributes="HG"; - console.writeln("Fighters defending sector"); - console.attributes="G"; - if(sector.Fighters==0) - console.writeln(" None"); - else { - console.write(" "+sector.Fighters); - if(sector.FighterOwner<0) - console.writeln(" (Cabal)"); - else if(sector.FighterOwner==player.Record) - console.writeln(" (yours)"); - else { - var otherplayer=players.Get(sector.FighterOwner); - console.write(" (belong to "+otherplayer.Alias); - if(otherplayer.TeamNumber) - console.write(" Team ["+otherplayer.TeamNumber+"]") - console.writeln(")"); - } - } - console.attributes="HW"; - console.write("Warps lead to "); - count=0; - for(i=0; i<sector.Warps.length; i++) { - if(sector.Warps[i] != 0) { - if(count) - console.write(", "); - console.write(sector.Warps[i]); - count++; - } - } - console.attributes="W"; - console.crlf(); -} - -function KilledBy(killed, killer, notify) /* 15300 */ -{ - var i; - - killed.KilledBy=killer.Record; - killed.Put(); - var killedLocation=playerLocation.Get(killed.Record); - killedLocation.Sector=killed.Sector; killedLocation.Put(); - - /* Destroy all deployed fighters */ - for(i=1; i<sectors.length; i++) { - var sector=sectors.Get(i); - if(sector.FighterOwner==player.Record) { - sector.Fighters=0; - sector.FighterOwner=0; - sector.Put(); - } - } - - if(killed.TeamNumber > 0) { - var team=teams.Get(killed.TeamNumber); - var i; - for(i=0; i<team.Members.length; i++) { - if(team.Members[i]==killed.Record) { - team.Members[i]=0; - team.Size--; - } - } - } - - if(notify) - twmsg.writeln(" - "+killer.Alias+" killed "+killed.Alias); -} - -function RankPlayers() -{ - var i; - var rank=new Array(); - var fighters=new Array(); - - for(i=1; i<sectors.length; i++) { - var sector=sectors.Get(i); - if(sector.Fighters > 0 && sector.FighterOwner > 0) { - if(fighters[sector.FighterOwner]==undefined) - fighters[sector.FighterOwner]=0; - fighters[sector.FighterOwner]+=sector.Fighters; - } - } - for(i=1; i<players.length; i++) { - var p=players.Get(i); - if(p.UserNumber==0) - continue; - if(p.KilledBy!=0) - continue; - var robj=new Object(); - robj.Record=p.Record; - robj.Score=p.Fighters*100 + p.Holds*500 + p.Credits; - for(i=0; i<Commodities.length; i++) - robj.Score += Commodities[i].price*p.Commodities[i]; - if(fighters[i]!=undefined) - robj.Score += fighters[i]*100; - rank.push(robj); - } - - function sortfunc(a,b) { - return(a.Score-b.Score); - } - - rank.sort(sortfunc); - return(rank); -} - -function TWRank() -{ - var rf=new File(fname(Settings.TopTenFile)); - rf.open("w"); - rf.writeln(); - rf.writeln(" T R A D E W A R S I I - 500T S C O R E B O A R D "); - rf.writeln(); - rf.writeln("Last updated at: "+system.timestr()); - rf.writeln(); - rf.writeln("Player Rankings"); - rf.writeln("Rank Value Team Player"); - rf.writeln("==== ============= ====== ================"); - var ranked=RankPlayers(); - var i; - var trank=new Object(); - - for(i=0; i<ranked.length; i++) { - var p=players.Get(ranked[i].Record); - if(i<10) - rf.writeln(format("%4d %13d %6s %s",(i+1),ranked[i].Score,p.TeamNumber==0?"":p.TeamNumber.toString(),p.Alias)); - if(p.TeamNumber.toString() != 0) { - if(trank[p.TeamNumber.toString()]==undefined) - trank[p.TeamNumber.toString()]=0; - trank[p.TeamNumber.toString()]+=ranked[i].Score; - } - } - var tsort=new Array(); - for(tr in trank) { - var ts=new Object(); - ts.Record=tr; - ts.Score=trank[tr]; - tsort.push(tr); - } - if(tsort.length > 0) { - function sortfunc(a,b) { - return(a.Score-b.Score); - } - - tsort.sort(sortfunc); - rf.writeln(); - rf.writeln("Team Rankings"); - rf.writeln("Rank Value Team"); - rf.writeln("==== ============= ======"); - for(i=0; i<tsort.length; i++) { - if(i>=10) - break; - rf.writeln(format("%4d %13d %6d",(i+1),tsort[i].Score,tsort[i].Record)); - } - } - rf.close(); -} - function do_exit() { player.Online=false; @@ -1162,83 +220,6 @@ function Instructions() } } -function DoBattle(opp, otherteam) -{ - if(player.Fighters<1) { - console.writeln("You don't have any fighters!"); - return(0); - } - else { - console.write("How many fighters do you wish to use? "); - var use=console.getnum(player.Fighters); - - if(use > 0 && use <= player.Fighters) { - var lost=0; - var killed=0; - - player.Fighters -= use; - while(use && opp.Fighters) { - if(player.TeamNumber > 0 && otherteam) { - if((random(10)+1) > 6) { - opp.Fighters--; - killed++; - } - else { - use--; - lost++; - } - } - else if(otherteam && player.TeamNumber==0) { - if((random(10)+1) > 6) { - use--; - lost++; - } - else { - opp.Fighters--; - killed++; - } - } - else { - if(random(2)==0) { - use--; - lost++; - } - else { - opp.Fighters--; - killed++; - } - } - } - player.Fighters += use; - opp.Put(); - player.Put(); - - console.writeln("You lost "+lost+" fighter(s), "+player.Fighters+" remain."); - if(opp.Fighters > 0) - console.write("You destroyed "+killed+" enemy fighters, "+opp.Fighters+" remain."); - else - console.write("You destroyed all of the enemy fighters."); - return(killed); - } - } - return(0); -} - -function SolReport() -{ - var holdprice=parseInt(50*Math.sin(.89756*(today/86400)) + .5)+500; - var fighterprice=parseInt(10*Math.sin(.89714*(today/86400) + 1.5707) + .5)+100; - var turnprice=300; - - console.writeln("Commerce report for Sol: " + system.timestr()); - console.writeln(" Cargo holds: " + holdprice + " credits/hold"); - console.writeln(" Fighters : " + fighterprice + " credits/fighter"); - console.writeln(" Turns : "+turnprice+" credits each."); - console.crlf(); - - return([holdprice,fighterprice,turnprice]); -} - function Production(place) { var newupd=time(); @@ -1257,1267 +238,3 @@ function Production(place) place.Put(); } -function PortReport(sec) { - var port=ports.Get(sec.Port); - var i; - - if(port==null) - return(null); - /* 33000 */ - Production(port); - var ret=new Array(Commodities.length); - for(i=0; i<Commodities.length; i++) { - ret[i]=new Object(); - ret[i].Vary=port.PriceVariance[i]; - ret[i].Number=parseInt(port.Commodities[i]); - ret[i].Price=parseInt(Commodities[i].price*(1-ret[i].Vary*ret[i].Number/port.Production[i]/1000)+.5); - } - console.crlf(); - console.writeln("Commerce report for "+port.Name+": "+system.timestr()); - console.crlf(); - console.writeln(" Items Status # units in holds"); - console.attributes="HK"; - console.writeln(" ===== ====== ======= ========"); - for(i=0; i<Commodities.length; i++) { - console.attributes=['HR','HG','HY','HB','HM','HC','HW'][i]; - console.writeln(format("%s %-7s %-7d %-7d", - Commodities[i].disp - ,ret[i].Vary<0?"Buying":"Selling" - ,ret[i].Number - ,player.Commodities[i])); - } - return(ret); -} - -function GetKeyEcho() -{ - var ret=console.getkey().toUpperCase(); - if(ret=="\x0a" || ret=="\x0d") - ret=''; - console.writeln(ret); - return(ret); -} - -function ShortestPath(start, end) -{ - var i,j; - var hops=0; - var univ=new Array(sectors.length); - var done=false; - var ret=new Array(); - - function MarkWarps(univ, pos, end, hops) - { - var i; - - for(i=0; i<univ[pos].Warps.length; i++) { - if(univ[pos].Warps[i]==0) - continue; - if(univ[univ[pos].Warps[i]]==undefined) { - univ[univ[pos].Warps[i]]=sectors.Get(univ[pos].Warps[i]); - univ[univ[pos].Warps[i]].hops=hops; - if(univ[pos].Warps[i]==end) - return(true); - } - } - return(false); - } - - /* Do the expansion */ - univ[start]=sectors.Get(start); - univ[start].hops=hops; - while(!done) { - for(i=1; i<sectors.length; i++) { - if(univ[i]!=undefined && univ[i].hops==hops) { - if(MarkWarps(univ, i, end, hops+1)) { - done=true; - break; - } - } - } - hops++; - } - ret.push(end); - for(i=end;i!=start;) { - var lasthop=i; - for(j=0; j<univ[i].Warps.length; j++) { - if(univ[univ[i].Warps[j]]!=undefined && univ[univ[i].Warps[j]].hops<univ[i].hops) { - i=univ[i].Warps[j]; - if(i!=start) - ret.unshift(i); - break; - } - } - if(i==lasthop) - return(null); - } - return(ret); -} - -function MatchPlayer(name) -{ - var i; - - name=name.toUpperCase(); - for(i=1; i<players.length; i++) { - var p=players.Get(i); - if(p.UserNumber==0) - continue; - if(p.KilledBy!=0) - continue; - if(p.Alias.toUpperCase().indexOf(name)!=-1) { - console.write(p.Alias+" (Y/N)[Y]? "); - switch(GetKeyEcho()) { - case 'N': - break; - default: - return(p); - } - } - } - console.writeln("Not found."); - return(null); -} - -function RadioMessage(from, to, msg) -{ - var i; - - var rmsg; - for(i=0; i<twrmsg.length; i++) { - var rmsg=twrmsg.Get(i); - if(rmsg.Read) - break; - rmsg=null; - } - if(rmsg==null) - rmsg=twrmsg.New(); - rmsg.Read=false; - rmsg.From=from; - rmsg.To=to; - rmsg.Message=msg; - rmsg.Put(); - console.writeln("Message sent."); - return; -} - -function CreatePlanet(sector) -{ - console.writeln("There isn't a planet in this sector."); - console.writeln("Planets cost 10,000 credits."); - if(player.Credits < 10000) { - console.writeln("You're too poor to buy one."); - return; - } - console.writeln("You have " + player.Credits + " credits."); - console.write("Do you wish to buy a planet(Y/N) [N]? "); - switch(GetKeyEcho()) { - case 'Y': - var i; - var planet; - for(i=1; i<planets.length; i++) { - planet=planets.Get(i); - if(!planet.Created) - break; - planet=null; - } - if(planet==null) { - console.crlf(); - console.writeln("I'm sorry, but all planets are taken."); - console.writeln("One has to be destroyed before you can buy a planet."); - } - else { - planet.Name=''; - while(planet.Name=='') { - console.write("What do you want to name this planet? (41 chars. max)? "); - planet.Name=console.getstr(41); - } - for(i=0; i<Commodities.length; i++) { - planet.Commodities[i]=1; - planet.Production[i]=1; - } - player.Credits-=10000; - player.Put(); - planet.Sector=sector.Record; - sector.Planet=planet.Record; - planet.LastUpdated=time(); - planet.Put(); - sector.Put(); - twmsg.writeln(" - "+player.Alias+" made a planet: "+planet.Name); - console.crlf(); - console.writeln("Planet created"); - break; - } - - default: - break; - } -} - -function PlanetReport(planet) -{ - console.crlf(); - console.attributes="HC"; - console.writeln("Planet: "+planet.Name); - console.writeln(" Item Prod. Amount in holds"); - console.attributes="HK"; - console.writeln(" ==== ===== ====== ========"); - var i; - var freeholds=player.Holds; - for(i=0; i<Commodities.length; i++) { - console.attributes=['HR','HG','HY','HB','HM','HC','HW'][i]; - console.writeln(format("%s %2d %6d %8d" - ,Commodities[i].disp - ,planet.Production[i] - ,parseInt(planet.Commodities[i]) - ,player.Commodities[i])); - freeholds-=player.Commodities[i]; - } - console.attributes="HG"; - console.writeln("You have "+freeholds+" free cargo holds."); -} - -function PlanetMenu(planet) -{ - var key; - var freeholds=player.Holds; - var i; - var values=new Array('A','I','D','L','R'); - - for(i=0; i<Commodities.length; i++) { - freeholds-=player.Commodities[i]; - values.push((i+1).toString()); - } - - while(true) { - console.crlf(); - console.write("Planet command (?=help)[A]? "); - key=InputFunc(values); - switch(key) { - case '': - case 'A': - console.writeln("<Take all>"); - if(freeholds < 1) { - console.writeln("You don't have any free holds."); - continue; - } - for(i=Commodities.length-1; i>=0; i--) { - var take=parseInt(planet.Commodities[i]); - if(take > freeholds) - take=freeholds; - if(take) { - console.writeln("You took " + take + " holds of "+Commodities[i].name.toLowerCase()); - player.Commodities[i]+=take; - planet.Commodities[i]-=take; - freeholds-=take; - } - if(freeholds < 1) { - console.writeln("Your cargo holds are full."); - break; - } - } - player.Put(); - planet.Put(); - break; - case 'I': - console.writeln("<Increase productivity>"); - console.crlf(); - console.writeln("You have "+player.Credits+" credits."); - var opts=""; - var values=new Array(); - for(i=0; i<Commodities.length; i++) { - console.writeln((i+1)+" - "+Commodities[i].name+" costs "+(Commodities[i].price*20)); - if(i) - opts += ','; - opts += (i+1).toString(); - values.push((i+1).toString()); - } - console.write("Which one do you want to increase ("+opts+")? "); - var keynum=parseInt(InputFunc(values)); - if(keynum > 0 && keynum <= Commodities.length) { - keynum--; - if(planet.Production[keynum]>19) { - console.writeln("It's at its maximum value."); - continue; - } - var max=parseInt(player.Credits/(Commodities[keynum].price*20)); - if(max<1) { - console.writeln("You're too poor. You only have "+player.Credits+" credits."); - continue; - } - if(planet.Production[keynum]+max > 19) - max=20-planet.Production[keynum]; - console.write(Commodities[keynum].name+": Increase by how many units? "); - var incr=console.getnum(max); - if(incr > 0 && incr <= max) { - player.Credits -= incr*Commodities[keynum].price*20; - planet.Production[keynum]+=incr; - planet.Put(); - player.Put(); - } - } - break; - case 'D': - console.crlf(); - console.attributes="RI7H"; - console.writeln("*** DESTROY THE PLANET ***"); - console.crlf(); - console.attributes="Y"; - console.write("Are you sure (Y/N)[N]? "); - if(GetKeyEcho()=='Y') { - planet.Created=false; - var sector=sectors.Get(planet.Sector); - sector.Planet=0; - planet.Sector=0; - planet.Put(); - sector.Put(); - twmsg.writeln(" - " + player.Alias + " destroyed the planet in sector " + sector.Record); - console.writeln("Planet destroyed."); - return; - } - break; - case 'L': - return; - case 'R': - PlanetReport(planet); - break; - case '?': - console.crlf(); - console.printfile(fname("planet.asc")); - break; - default: - var keynum=parseInt(key); - if(keynum > 0 && keynum <= Commodities.length) { - keynum--; - var max=freeholds; - if(max > parseInt(planet.Commodities[keynum])) - max=parseInt(planet.Commodities[keynum]); - console.writeln("<Take "+Commodities[keynum].name.toLowerCase()+">"); - console.write("How much [" + max + "]? "); - var take=console.getnum(max); - if(take > max) { - console.writeln("They don't have that many."); - continue; - } - if(take > freeholds) { - console.writeln("You don't have enough free cargo holds."); - continue; - } - planet.Commodities[keynum]-=take; - player.Commodities[keynum]+=take; - freeholds -= take; - planet.Put(); - player.Put(); - } - else { - console.writeln("Invalid command. Enter ? for help"); - } - } - } -} - -function ReadRadio() -{ - var i; - var rmsg; - var count=0; - - console.crlf(); - console.writeln("Checking for Radio Messages sent to you."); - for(i=0; i<twrmsg.length; i++) { - var rmsg=twrmsg.Get(i); - if(rmsg.Read) - continue; - if(rmsg.To != player.Record) - continue; - console.write("Message from "); - if(rmsg.From > 0) { - var p=players.Get(rmsg.From); - console.write(p.Alias); - } - else { - console.write("A deleted player"); - } - console.writeln(":"); - console.writeln(rmsg.Message); - rmsg.Read=true; - rmsg.Put(); - count++; - } - if(count < 1) - console.writeln("None Received."); -} - -function Transact(type, price, vary, avail) -{ - var buy=vary<0?false:true; - var youare=buy?"buy":"sell"; - var weare=buy?"sell":"buy"; - var emptyholds=player.Holds; - var max=0; - - var i; - for(i=0; i<Commodities.length; i++) - emptyholds -= player.Commodities[i]; - - if(buy) - max=emptyholds; - else - max=player.Commodities[type]; - - if(max > parseInt(avail)) - max=parseInt(avail); - - if(max < 1) - return(-1); - - console.crlf(); - console.writeln("You have "+player.Credits+" credits and "+emptyholds+" empty cargo holds."); - console.crlf(); - console.writeln("We are "+weare+"ing up to "+avail+". You have "+player.Commodities[type]+" in your holds."); - - console.write("How many holds of "+Commodities[type].name.toLowerCase()+" do you want to "+youare+" ["+max+"]? "); - var amount=console.getnum(max,max); - - if(amount>0 && amount<=max) { - var done=false; - console.writeln("Agreed, "+amount+" units."); - var haggles=random(3)+2; - var offer=0; - for(var hag=0; hag<haggles; hag++) { - if(hag==haggles-1) - console.write("Our final offer is "); - else - console.write("We'll "+weare+" them for "); - console.writeln(parseInt(price*amount*(1+vary/1000)+.5)); - offer=0; - while(offer==0) { - console.write("Your offer? "); - offer=console.getnum(buy?player.Credits:(price*amount*10)); - if(offer==0) - break; - if(offer < price*amount/10 || offer > price*amount*10) { - console.writeln("That was pretty funny, Now make a serious offer."); - offer=0; - } - } - if(offer==0) - break; - if(!buy && offer <= price*amount) { - console.writeln("We'll take them!"); - player.Credits += offer; - player.Commodities[type] -= amount; - player.Put(); - return(amount); - } - if(buy && offer >= price*amount) { - console.writeln("Sold!"); - player.Credits -= offer; - player.Commodities[type] += amount; - player.Put(); - return(amount); - } - var worstoffer=parseInt(amount*price*(1-vary/250/(hag+1)) + .5); - if(buy && offer < worstoffer) - break; - if(!buy && offer > worstoffer) - break; - price = .7*price + .3*offer/amount; - } - - if(offer > 0) { - if(buy) { - console.writeln("Too low. We'll sell them to local traders."); - return(0); - } - console.writeln("Too high. We'll buy them from local traders."); - } - return(0); - } - return(0); -} - -function TeamMenu() -{ - - function TeamHelp() { - console.crlf(); - if(player.TeamNumber > 0) - console.printfile(fname("team-member.asc")); - else - console.printfile(fname("team-none.asc")); - } - - TeamHelp(); - - while(1) { - var values=new Array(); - if(player.TeamNumber > 0) - values=['1','2','3','4','5','6','7','?']; - else - values=['1','2','3','?']; - console.crlf(); - console.attributes="W"; - console.write("Team Command (?=help)? "); - switch(InputFunc(values)) { - case '?': - TeamHelp(); - break; - case '1': - return; - case '2': - if(player.TeamNumber > 0) { - console.writeln("You already belong to a Team! "); - console.writeln("You must quit a team to form another Team."); - break; - } - var password=''; - while(password.length != 4) { - console.writeln("To form a Team you will need to input a 4 character Team Password"); - console.write("Enter Password [ENTER]=quit? "); - password=console.getstr(4); - if(password=='') - break; - if(password.length != 4) - console.writeln("Password MUST be 4 characters"); - } - if(password=='') - break; - console.crlf(); - console.writeln("REMEMBER YOUR TEAM PASSWORD!"); - var team=null; - for(i=1; i<teams.length; i++) { - team=teams.Get(i); - if(team.Size > 0) - break; - team=null; - } - if(team==null) - team=teams.New(); - team.Password=password; - team.Size=1; - team.Members[0]=player.Record; - player.TeamNumber=team.Record; - team.Put(); - player.Put(); - console.attributes="HYI"; - twmsg.writeln(player.Alias+" Created Team "+team.Record+" the " /* TNAM$ */); - console.writeln("Team number [" + team.Record + "] CREATED!"); - console.attributes="HK"; - break; - case '3': - if(player.TeamNumber > 0) { - console.writeln("You already belong to a Team! "); - console.writeln("You must quit one team to join another Team."); - break; - } - console.write("What Team number do you wish to join (0=quit)? "); - var tnum=console.getnum(teams.length-1); - if(tnum > 0 && tnum < teams.length) { - var team=teams.Get(tnum); - if(team.Size > 3) { - console.writeln("The Team you picked has a maximum amount of members!"); - break; - } - console.write("Please enter Password to Join Team #"+team.Record+" ? "); - var pass=console.getstr(4); - if(pass != team.Password) { - console.writeln("Invalid Password entered!"); - break; - } - var i; - for(i=0; i<team.Members.length; i++) { - if(team.Members[i]==0) { - team.Members[i]=player.Record; - team.Size++; - player.TeamNumber=team.Record; - team.Put(); - player.Put(); - twmsg.writeln(player.Alias + " Joined Team "+team.Record); - console.attributes="HC"; - console.writeln("Your Team info has been recorded! Have fun!"); - console.attributes="HK"; - break; - } - } - } - break; - case '4': - if(player.TeamNumber != 0) { - console.writeln("You don't belong to a Team!"); - break; - } - console.write("Are you sure you wish to quit your Team [N]? "); - if(GetKeyEcho()=='Y') { - var team=teams.Get(player.TeamNumber); - player.TeamNumber=0; - var i; - for(i=0; i<team.Members.length; i++) { - if(team.Members[i]==player.Record) { - team.Members[i]=0; - team.Size--; - player.Put(); - team.Put(); - console.crlf(); - console.attributes="HG"; - console.writeln("You have been removed from Team play"); - console.attributes="HK"; - } - } - } - break; - case '5': - console.write("Transfer Credits to another Team member [N]? "); - if(GetKeyEcho()=='Y') { - if(player.Credits < 1) { - console.writeln("You don't have any Credits."); - break; - } - var i; - - var otherplayer=null; - for(i=1;i<players.length; i++) { - var otherloc=playerLocation.Get(i); - if(otherloc.Sector==player.Sector) { - otherplayer=players.Get(i); - if(otherplayer.Sector==player.Sector - && otherplayer.Record!=player.Record - && otherplayer.KilledBy!=0 - && otherplayer.UserNumber!=0 - && otherplayer.TeamNumber==player.TeamNumber) { - console.write("Transfer Credits to " + otherplayer.Alias + " (Y/[N])? "); - if(GetKeyEcho()=='Y') - break; - } - otherplayer=null; - } - } - if(otherplayer==null) { - console.writeln("There is no one else in this sector"); - break; - } - while(1) { - console.writeln("You have" + player.Credits + " credits."); - console.writeln(otherplayer.Alias + " has" + otherplayer.Credits + " credits."); - console.write("How many Credits do you wish to Transfer? "); - var transfer=console.getnum(player.Credits); - if(transfer<1 || transfer > player.Credits) - break; - if(otherplayer.Credits + transfer > 25000) { - console.writeln("You Team mate will have more than 25,000 credits"); - console.write("Do you wish to complete the Transfer [N]? "); - if(GetKeyEcho()=='Y') - break; - } - else - break; - } - otherplayer.Credits += transfer; - player.Credits -= transfer; - player.Put(); - otherplayer.Put(); - console.writeln("Credits Transfered!"); - } - case '6': - console.write("Transfer Fighters to another Team member [N]? "); - if(GetKeyEcho()=='Y') { - if(player.Fighters < 1) { - console.writeln("You don't have any Fighters."); - break; - } - var i; - - var otherplayer=null; - for(i=1;i<players.length; i++) { - var otherloc=playerLocation.Get(i); - if(otherloc.Sector==player.Sector) { - otherplayer=players.Get(i); - if(otherplayer.Sector==player.Sector - && otherplayer.Record!=player.Record - && otherplayer.KilledBy!=0 - && otherplayer.UserNumber!=0 - && otherplayer.TeamNumber==player.TeamNumber) { - console.write("Transfer Fighters to " + otherplayer.Alias + " (Y/[N])? "); - if(GetKeyEcho()=='Y') - break; - } - } - otherplayer=null; - } - if(otherplayer==null) { - console.writeln("There is no one else in this sector"); - break; - } - while(1) { - console.writeln("You have" + player.Fighters + " fighters."); - console.writeln(otherplayer.Alias + " has" + otherplayer.Fighters + " fighters."); - console.write("How many Fighters do you wish to Transfer? "); - var transfer=console.getnum(player.Fighters); - if(transfer<1 || transfer > player.Fighters) - break; - if(otherplayer.Fighters + transfer > 9999) - console.writeln("Maximum amount of fighters per player is 9999"); - else - break; - } - otherplayer.Fighters += transfer; - player.Fighters -= transfer; - player.Put(); - otherplayer.Put(); - console.writeln("Fighters Transfered!"); - } - case '7': - console.writeln("Locating Other Team members."); - console.crlf(); - console.writeln("Name Sector"); - console.writeln("==================== ======"); - var count=0; - var i; - for(i=1;i<players.length; i++) { - otherplayer=players.Get(i); - if(otherplayer.Record!=player.Record - && otherplayer.UserNumber!=0 - && otherplayer.TeamNumber==player.TeamNumber) { - count++; - } - console.write(format("%-41s ",otherplayer.Alias)); - if(otherplayer.KilledBy != 0) - console.write(" Dead!"); - else - console.write(otherplayer.Sector); - console.crlf(); - } - console.crlf(); - if(count==0) - console.writeln("None Found"); - break; - } - } -} - -function CabalAttack(cabal) -{ - /* Cabal groups lower than 6 (wandering and defence) do not attack players */ - if(cabal.Record < 6) - return; - - /* Look for another player in the sector (attacking by rank) */ - var i; - var attackwith=0; - - var ranks=RankPlayers(); - var sector=sectors.Get(cabal.Sector); - if(sector.FighterOwner != -1) /* Huh? */ - return; - - sector.Fighters -= cabal.Size; - if(sector.Fighters < 0) - sector.Fighters=0; - - for(i=0; i<ranks.length; i++) { - var otherplayer=players.Get(ranks[i].Record); - - if(otherplayer.Sector != cabal.Sector) - continue; - if(otherplayer.UserNumber==0) - continue; - if(otherplayer.KilledBy != 0) - continue; - else if(cabal.Record<9) /* Attack Group */ - attackwith=20; - else if(cabal.Record==9) { /* Top player hunter */ - if(i==0) - attackwith=cabal.Size; - else - attackwith=0; - } - - if(attackwith==0) - continue; - if(attackwith > cabal.Size) - attackwith = cabal.Size; - - cabal.Size -= attackwith; - /* Attack the player */ - var killed=0; - var lost=0; - while(otherplayer.Fighters > 0 && attackwith > 0) { - if(random(2)==1) { - attackwith--; - lost++; - } - else { - otherplayer.Fighters--; - killed++; - } - } - cabal.Size += attackwith; - twmsg.writeln(" Group "+cabal.Record+" --> "+otherplayer.Alias+": lost "+killed+ ", dstrd "+killed+" ("+(cabal.Size==0?"Cabal":"Player")+" dstrd)"); - if(cabal.Size==0) - cabal.ReInit(); - else { /* Player destroyed by the cabal! */ - otherplayer.KilledBy=-1; - var loc=playerLocation.Get(otherplayer.Record); - loc.Sector=0; - loc.Put(); - } - otherplayer.Put(); - cabal.Put(); - } - sector.Fighters += cabal.Size; - if(cabal.Size > 0) - sector.FighterOwner=-1; - sector.Put(); -} - -function MoveCabalGroup(cabal, target) -{ - if(cabal.Sector==0 || cabal.Size < 1) - return; - var sector=sectors.Get(cabal.Sector); - - sector.Fighters -= cabal.Size; - if(sector.Fighters < 1) { - sector.Fighters=0; - sector.FighterOwner=0; - } - sector.Put(); - - /* Set new sector */ - cabal.Sector=target; - sector=sectors.Get(cabal.Sector); - - /* Attack dropped fighters */ - if(sector.Fighters > 0 && sector.FighterOwner != -1) { - var killed=0; - var lost=0; - var ownername="Deleted Player"; - if(sector.FighterOwner > 0) { - var fowner=players.Get(sector.FighterOwner); - ownername=fowner.Alias; - } - while(cabal.Size > 0 && sector.Fighters > 0) { - if(random(2)==1) { - cabal.Size--; - lost++; - } - else { - sector.Fighters--; - killed++; - } - } - /* Place into twpmsg.dat */ - var i; - var msg=null; - for(i=0; i<twpmsg.length; i++) { - msg=twpmsg.Get(i); - if(msg.Read) - break; - msg=null; - } - if(msg==null) - msg=twpmsg.New(); - msg.Read=false; - msg.To=sector.FighterOwner; - msg.From=-1; - msg.Destroyed=killed; - msg.Put(); - twmsg.writeln(" Group "+cabal.Record+" --> Sector "+target+" ("+ownername+"): lost "+killed+", dstrd "+lost+" ("+(sector.Fighters==0?"Player":"Cabal")+" ftrs dstrd)"); - if(cabal.Size==0) { - cabal.ReInit(); - cabal.Put(); - return; - } - else { - sector.FighterOwner=-1; - sector.Fighters=cabal.Size; - } - sector.Put(); - } - - CabalAttack(cabal); - if(cabal.Sector==0 || cabal.Size < 1) - return; - - /* Merge into another group */ - var i; - for(i=1; i<cabals.length; i++) { - if(i==cabal.Record) - continue; - var othercabal=cabals.Get(i); - /* Merge Groups */ - if(othercabal.Sector==cabal.Sector) { - if(othercabal.Record < cabal.Record) { - othercabal.Size += cabal.Size; - cabal.ReInit(); - } - else { - cabal.Size += othercabal.Size; - othercabal.ReInit(); - } - cabal.Put(); - othercabal.Put(); - } - } -} - -function MoveCabal() -{ - var total=0; - var i; - - console.writeln("Moving the Cabal."); - twmsg.writeln(" Cabal report:"); - /* Validate Groups and count the total */ - for(i=1; i<cabals.length; i++) { - var cabal=cabals.Get(i); - var sector=sectors.Get(cabal.Sector); - cabal.Size=sector.Fighters; - if(sector.FighterOwner != -1 || sector.Fighters==0) { - cabal.Sector=0; - cabal.Size=0; - cabal.Goal=0; - } - cabal.Put(); - total+=cabal.Size; - } - - /* Move group 2 into sector 85 (merge into group 1) */ - var cabal=cabals.Get(2); - MoveCabalGroup(cabal, 85); - - /* Note, this seems to have a max limit of 2000 for regeneration */ - var regen=Settings.CabalRegeneration; - if(total+regen > 2000) - regen=2000-total; - if(regen<1) - regen=0; - - cabal=cabals.Get(1); - cabal.Size += regen; - - /* Split off group 2 */ - group2=cabals.Get(2); - if(cabal.Size > 1000) { - group2.Size=cabal.Size-1000; - group2.Sector=85; - MoveCabalGroup(group2, 83); - } - - /* Create wandering groups */ - for(i=3; i<6; i++) { - var wgroup=cabals.Get(i); - if(wgroup.Size < 1 || wgroup.Sector < 1 || wgroup.Sector >= sectors.length) { - if(group2.size >= 600) { - wgroup.Size=100; - group2.size-=100; - wgroup.Sector=83; - wgroup.Goal=0; - while(wgroup.Goal < 8) - wgroup.Goal=random(sectors.length); - } - else { - wgroup.ReInit(); - } - wgroup.Put(); - } - } - - /* Create attack groups */ - for(i=6; i<9; i++) { - var agroup=cabals.Get(i); - if(agroup.Size < 1 || agroup.Sector < 1 || agroup.Sector >= sectors.length) { - if(group2.size >= 550) { - agroup.Size=50; - group2.size-=50; - agroup.Sector=83; - agroup.Goal=0; - while(agroup.Goal < 8) - agroup.Goal=random(sectors.length); - } - else { - agroup.ReInit(); - } - agroup.Put(); - } - } - - /* Create hunter group */ - var hgroup=cabals.Get(9); - if(hgroup.Size < 1 || hgroup.Sector < 1 || hgroup.Sector >= sectors.length) { - if(group2.size >= 500) { - hgroup.Size=group2.Size-500; - group2.size-=hgroup.Size; - hgroup.Sector=83; - hgroup.Goal=0; - } - else { - hgroup.ReInit(); - } - hgroup.Put(); - } - group2.Put(); - - /* Move wandering groups */ - for(i=3; i<6; i++) { - var wgroup=cabals.Get(i); - if(wgroup.Size < 1 || wgroup.Sector == 0) - continue; - /* Choose new target */ - if(wgroup.Sector == wgroup.Goal) { - wgroup.Goal=0; - while(wgroup.Goal < 8) - wgroup.Goal=random(sectors.length); - } - if(wgroup.Size < 50 || wgroup.Size > 100) - wgroup.Goal=85; - var path=ShortestPath(wgroup.Sector, wgroup.Goal); - while(path[0] < 8) - path.shift(); - MoveCabalGroup(wgroup,path[0]); - } - - /* Move Attack Groups */ - for(i=6; i<9; i++) { - var agroup=cabals.Get(i); - if(agroup.Size < 1 || agroup.Sector == 0) - continue; - /* Choose new target */ - if(agroup.Sector == agroup.Goal) { - agroup.Goal=0; - while(agroup.Goal < 8) - agroup.Goal=random(sectors.length); - } - if(agroup.Size < 20 || agroup.Size > 50) - agroup.Goal=85; - var path=ShortestPath(agroup.Sector, agroup.Goal); - var next; - while(path.length > 0 && agroup.Size > 0) { - var next=path.shift(); - if(next < 8) - continue; - MoveCabalGroup(agroup,next); - } - } - - /* Move hunter groups... */ - for(i=9; i<10; i++) { - var hgroup=cabals.Get(i); - if(hgroup.Size < 1 || hgroup.Sector == 0) - continue; - /* Choose target */ - var ranks=RankPlayers(); - if(ranks.length < 0) { - var player=players.Get(ranks[0].Record); - hgroup.Goal=player.Sector; - var path=ShortestPath(hgroup.Sector, hgroup.Goal); - var next; - while(path.length > 0 && hgroup.Size > 0) { - var next=path.shift(); - MoveCabalGroup(agroup,next); - } - } - } -} - -function DeletePlayer(player) -{ - /* Delete player */ - player.ReInit(); - player.UserNumber=0; - player.Alias="<Deleted>"; - player.Sector=0; - player.Put(); - /* Move to sector zero */ - var loc=playerLocation.Get(player.Record); - loc.Sector=0; - loc.Put(); - /* Set fighter owner to "Deleted Player" */ - var i; - for(i=1; i<sectors.length; i++) { - var sector=sectors.Get(i); - if(sector.FighterOwner==player.Record) { - sector.FighterOwner=-98; - sector.Put(); - } - } - /* Set messages TO the deleted player as read and FROM as from deleted */ - for(i=0; i<twpmsg.length; i++) { - var msg=twpmsg.Get(i); - - if(msg.To==player.Record && !msg.Read) { - msg.Read=true; - msg.Put(); - } - else if(msg.From==player.Record) { - msg.From=-98; - msg.Put(); - } - } - /* Set radio messages TO the deleted player as read and FROM as from deleted */ - for(i=0; i<twrmsg.length; i++) { - var msg=twrmsg.Get(i); - - if(msg.To==player.Record && !msg.Read) { - msg.Read=true; - msg.Put(); - } - else if(msg.From==player.Record) { - msg.From=-98; - msg.Put(); - } - } - /* Set killed bys to Deleted Player */ - for(i=1; i<players.length; i++) { - var otherplayer=players.Get(i); - - if(otherplayer.KilledBy==player.Record) { - otherplayer.KilledBy=-98; - otherplayer.Put(); - } - } - twmsg.writeln(" - "+player.Alias+" deleted from game"); -} - -var lastmisc=system.node_list[bbs.node_num-1].misc; -var laststatus=system.node_list[bbs.node_num-1].status; -function InputFunc(values) -{ - var str=''; - var pos=0; - var insertmode=true; - var key; - var origattr=console.attributes; - var matchval=''; - - console.line_counter=0; - console.attributes="N"; -InputFuncMainLoop: - for(;;) { - key=console.inkey(100); - if(key == '') { - /* Node status check */ - var newmisc=system.node_list[bbs.node_num-1].misc; - var newstatus=system.node_list[bbs.node_num-1].status; - if(newmisc != lastmisc || newstatus != laststatus) { - console.saveline(); - bbs.nodesync(); - console.write("\r"); - if(console.line_counter!=0) { - console.crlf(); - console.line_counter=0; - } - console.restoreline(); - lastmisc=system.node_list[bbs.node_num-1].misc; - laststatus=system.node_list[bbs.node_num-1].status; - } - - /* Busy loop checking */ - } - else { - switch(key) { - case '\x1b': /* Escape */ - matchval=''; - pos=0; - break InputFuncMainLoop; - case '\r': - break InputFuncMainLoop; - case '\x08': /* Backspace */ - if(pos==0) - break; - console.write('\x08 \x08'); - str=str.substr(0,-1); - pos--; - /* Fall-through */ - default: - if(key != '\x08') { - /* No CTRL chars (evar!) */ - if(ascii(key)<32) - break; - str=str.substr(0,pos)+key+str.substr(pos); - pos++; - console.write(key); - } - /* Is this an exact match AND the longest possible match? */ - var value; - var exact_match=false; - var longer_match=false; - matchval=''; - for(value in values) { - if(typeof(values[value])=='string') { - var ucv=values[value].toUpperCase(); - var ucs=str.toUpperCase(); - if(ucv==ucs) { - exact_match=true; - matchval=values[value]; - } - else if(ucv.indexOf(ucs)==0) - longer_match=true; - } - else if(typeof(values[value])=='object') { - var min=0; - var max=4294967295; - var def=0; - if(values[value].min != undefined) - min=values[value].min; - if(values[value].max != undefined) - max=values[value].max; - if(values[value].def != undefined) - def=values[value].def; - if(str.search(/^[0-9]*$/)!=-1) { - var cur=def; - if(pos > 0) - cur=parseInt(str); - if(cur >= min && cur <= max) { - exact_match=true; - matchval=cur; - } - if(cur*10 <= max) - longer_match=true; - } - } - } - if(exact_match && !longer_match) - break InputFuncMainLoop; - /* That's not valid! */ - if((!longer_match) && pos > 0) { - console.write('\x08 \x08'); - str=str.substr(0,-1); - pos--; - } - } - } - } - - while(pos > 0) { - console.write('\x08'); - pos--; - } - console.cleartoeol(origattr); - console.write(matchstr.toString()); - console.crlf(); - return(matchstr); -} - -function MoveTo(to) -{ - var sector=sectors.Get(player.Sector); - - if(to > 0) { - for(i=0; i<sector.Warps.length; i++) { - if(sector.Warps[i]==to) { - player.TurnsLeft--; - player.LastIn=player.Sector; - player.Sector=to; - player.Put(); - location.Sector=player.Sector; location.Put(); - if(player.TurnsLeft==10 || player.TurnsLeft < 6) { - console.writeln("You have " + player.TurnsLeft + " turns left."); - } - return(true); - } - } - console.writeln("You can't get there from here."); - } - return(false); -}