Compare commits

...

5 Commits

Author SHA1 Message Date
creme 90eb04a45f
update to 1.4.2 2020-02-13 01:01:35 +01:00
creme ac469ff3cf
change company names to default 2020-02-13 00:51:12 +01:00
creme 0b19f36306
revert to default game settings 2020-02-12 13:38:51 +01:00
creme 9b40f1080d
update to version 1.4.0
- remove trailing spaces
2020-02-11 18:32:43 +01:00
creme f170a6bf9a Merge branch 'master' of jan6/starlanes into master 2020-02-11 12:05:00 -05:00
8 changed files with 134 additions and 127 deletions

View File

@ -39,8 +39,3 @@ fakeinstall:
@echo chown root:root $(INSTALLDIR)/man/man6/starlanes.6 @echo chown root:root $(INSTALLDIR)/man/man6/starlanes.6
@echo chmod 755 $(INSTALLDIR)/bin/starlanes @echo chmod 755 $(INSTALLDIR)/bin/starlanes
@echo chmod 444 $(INSTALLDIR)/man/man6/starlanes.6 @echo chmod 444 $(INSTALLDIR)/man/man6/starlanes.6

12
README
View File

@ -8,7 +8,8 @@ I removed the AI, at least for now
(feel free to add it back if you figure out how to properly fix it) (feel free to add it back if you figure out how to properly fix it)
I also changed the company names slightly, and adjusted the stats for no reason I also changed the company names slightly, and adjusted the stats for no reason
most importantly, after experiencing troubles where someone accidentally closed most importantly, after experiencing troubles where someone accidentally closed
the final stats screen, I modified it to only close when pressing Y (doesn't matter if lower or uppercase) the final stats screen, I modified it to only close when pressing Y (doesn't
matter if lower or uppercase)
there are still plenty of warnings left to fix, there are still plenty of warnings left to fix,
but they don't affect the gameplay but they don't affect the gameplay
@ -27,12 +28,12 @@ one. Hence the make file may need adjusting.
For instance sometimes the curses program is For instance sometimes the curses program is
called plain curses and sometimes ncurses called plain curses and sometimes ncurses
It also expects there to be a /man/man6/ directory It also expects there to be a /man/man6/ directory
in which case you should in which case you should
Please, if you have any problems while installing Please, if you have any problems while installing
let me, David, know ("dejvid@zamir.net" and let me, David, know ("dejvid@zamir.net" and
"dejvid@barnsdle.demon.co.uk") even if you "dejvid@barnsdle.demon.co.uk") even if you
solve them. solve them.
Of course you can always just change to the directory where Of course you can always just change to the directory where
you installed starlanes and type "./starlanes" you installed starlanes and type "./starlanes"
@ -50,4 +51,3 @@ first published in Creative Computing magazine.
-Beej -Beej
beej@ecst.csuchico.edu beej@ecst.csuchico.edu

131
ai.c
View File

@ -5,12 +5,12 @@
** modify it under the terms of the GNU General Public License ** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2 ** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version. ** of the License, or (at your option) any later version.
** **
** This program is distributed in the hope that it will be useful, ** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details. ** GNU General Public License for more details.
** **
** You should have received a copy of the GNU General Public License ** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software ** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@ -22,23 +22,22 @@
#include "common.h" #include "common.h"
/* /*
int move; int move;
char map[120]; */ char map[120]; */
/* /*
**void generate_nme(nme) **void generate_nme(nme)
**used in place of getting name from humans **used in place of getting name from humans
*/ */
#define up_obj(move) (((move)-MAPX < 0)?OFFMAP:map[(move)-MAPX]) #define up_obj(move) (((move)-MAPX < 0)?OFFMAP:map[(move)-MAPX])
#define down_obj(move) (((move)+MAPX >= MAPX*MAPY)?OFFMAP:map[(move)+MAPX]) #define down_obj(move) (((move)+MAPX >= MAPX*MAPY)?OFFMAP:map[(move)+MAPX])
#define left_obj(move) (((move)%MAPX)?map[(move)-1]:OFFMAP) #define left_obj(move) (((move)%MAPX)?map[(move)-1]:OFFMAP)
#define right_obj(move) (((move)%MAPX == MAPX-1)?OFFMAP:map[(move)+1]) #define right_obj(move) (((move)%MAPX == MAPX-1)?OFFMAP:map[(move)+1])
void generate_nme(char *nme) void generate_nme(char *nme)
{ {
static int nmeNmr=0; static int nmeNmr=0;
switch(nmeNmr) { switch(nmeNmr) {
@ -60,7 +59,7 @@ enum investstatus { none,small ,signif,main };// type;
/* getfarmove gets the charecter value of a location 2 steps away. /* getfarmove gets the charecter value of a location 2 steps away.
** It makes no distiction between an empty space and an off map ** It makes no distiction between an empty space and an off map
** location ** location
*/ */
char getfarmove(enum farcompass fcom, char *map, int loc) char getfarmove(enum farcompass fcom, char *map, int loc)
{ {
@ -68,13 +67,13 @@ char getfarmove(enum farcompass fcom, char *map, int loc)
static int MAPY=My; static int MAPY=My;
char ch; char ch;
switch(fcom) { switch(fcom) {
case NorthW: if ((loc-1*MAPX )< 0) ch=SPACE; case NorthW: if ((loc-1*MAPX )< 0) ch=SPACE;
else { else {
ch=left_obj(loc-1*MAPX); ch=left_obj(loc-1*MAPX);
} }
break; break;
case FNorth: if ((loc-2*MAPX )< 0) ch=SPACE; else ch=map[loc-2*MAPX];break; case FNorth: if ((loc-2*MAPX )< 0) ch=SPACE; else ch=map[loc-2*MAPX];break;
case NorthE: if ((loc-1*MAPX )< 0) ch=SPACE; case NorthE: if ((loc-1*MAPX )< 0) ch=SPACE;
else { else {
ch=right_obj(loc-1*MAPX); ch=right_obj(loc-1*MAPX);
} }
@ -82,19 +81,19 @@ char getfarmove(enum farcompass fcom, char *map, int loc)
case FEast: if ((loc%MAPX)!=((loc+2)%MAPX)) ch=map[loc+2]; case FEast: if ((loc%MAPX)!=((loc+2)%MAPX)) ch=map[loc+2];
else ch=SPACE ; else ch=SPACE ;
break; break;
case SouthE: if ((loc+MAPX )> (MAPX*MAPY)) ch=SPACE; case SouthE: if ((loc+MAPX )> (MAPX*MAPY)) ch=SPACE;
else { else {
ch=right_obj(loc+1*MAPX); ch=right_obj(loc+1*MAPX);
} }
case FSouth: if ((loc+2*MAPX) > (MAPX*MAPY)) ch=SPACE; else ch=map[loc-2*MAPX];break; case FSouth: if ((loc+2*MAPX) > (MAPX*MAPY)) ch=SPACE; else ch=map[loc-2*MAPX];break;
/*(((loc)+2*MAPX > MAPX*MAPY)?SPACE:map[(loc)+2*MAPX]);break;*/ /*(((loc)+2*MAPX > MAPX*MAPY)?SPACE:map[(loc)+2*MAPX]);break;*/
case SouthW: if ((loc+MAPX )> (MAPX*MAPY)) ch=SPACE; case SouthW: if ((loc+MAPX )> (MAPX*MAPY)) ch=SPACE;
else { else {
ch=left_obj(loc+1*MAPX); ch=left_obj(loc+1*MAPX);
} }
case FWest: if ((loc%MAPX)!=((loc-2)%MAPX)) ch=map[loc-2]; case FWest: if ((loc%MAPX)!=((loc-2)%MAPX)) ch=map[loc-2];
else ch=SPACE ; else ch=SPACE ;
break; break;
/*if ((loc%MAPX)!=(loc-2)%MAPX))) ch=map[(loc)-2];else ch=SPACE;break;*/ /*if ((loc%MAPX)!=(loc-2)%MAPX))) ch=map[(loc)-2];else ch=SPACE;break;*/
default: ch= '?';break; default: ch= '?';break;
}; };
@ -105,13 +104,13 @@ enum compass revdir(enum compass dir)
{ {
enum compass rev; enum compass rev;
switch(dir) { switch(dir) {
case North:rev=South; break; case North:rev=South; break;
case East:rev=West; break; case East:rev=West; break;
case West:rev=East; break; case West:rev=East; break;
case South:rev=North; break; case South:rev=North; break;
} }
return rev; return rev;
} }
int onestep(enum compass dir, int loc) int onestep(enum compass dir, int loc)
{ {
@ -119,16 +118,16 @@ int onestep(enum compass dir, int loc)
switch(dir) { switch(dir) {
case North:if ((loc)-Mx < 0) newloc=-1; case North:if ((loc)-Mx < 0) newloc=-1;
else newloc=loc-Mx; else newloc=loc-Mx;
break; break;
case South:if ((loc)+Mx > Mx*My) newloc=-1; case South:if ((loc)+Mx > Mx*My) newloc=-1;
else newloc=loc+Mx; else newloc=loc+Mx;
break; break;
case West: if ((loc)%Mx ==0)newloc=-1; case West: if ((loc)%Mx ==0)newloc=-1;
else newloc=loc-1; else newloc=loc-1;
break; break;
case East: if ((loc)%Mx ==Mx-1)newloc=-1; case East: if ((loc)%Mx ==Mx-1)newloc=-1;
else newloc=loc+1; else newloc=loc+1;
break; break;
} }
return newloc; return newloc;
} }
@ -142,7 +141,7 @@ int onestep(enum compass dir, int loc)
*/ */
char placemove(PLAYER *pla,int *move, COMPANY *co, int turn,char *map, int Difficulty) char placemove(PLAYER *pla,int *move, COMPANY *co, int turn,char *map, int Difficulty)
{ {
static int MAPX=Mx ,MAPY=My; static int MAPX=Mx ,MAPY=My;
char mvch; long moveval[NUMMOVES]; int neighb[4];int nc, ncom; char mvch; long moveval[NUMMOVES]; int neighb[4];int nc, ncom;
enum compass dir; enum compass dir;
@ -156,10 +155,10 @@ char placemove(PLAYER *pla,int *move, COMPANY *co, int turn,char *map, int Diffi
mvch= '1'; mvch= '1';
curMax=-1000; curMax=-1000;
if ((Difficulty>1 )||(rand()%100>50)) if ((Difficulty>1 )||(rand()%100>50))
for (curCo=0;curCo<=NUMCO;curCo++){ for (curCo=0;curCo<=NUMCO;curCo++){
tothold[curCo] =0; tothold[curCo] =0;
/*finds the proportion of holdings relativ to other players*/ /*finds the proportion of holdings relativ to other players*/
for (curpl=0;curpl<MAXPLAYERS;curpl++) for (curpl=0;curpl<MAXPLAYERS;curpl++)
tothold[curCo]=pla[curpl].holdings[curCo] +tothold[curCo]; tothold[curCo]=pla[curpl].holdings[curCo] +tothold[curCo];
if (tothold[curCo]==0) coholdings[curCo]=0; if (tothold[curCo]==0) coholdings[curCo]=0;
else coholdings[curCo]=pla[turn].holdings[curCo]/tothold[curCo]; else coholdings[curCo]=pla[turn].holdings[curCo]/tothold[curCo];
@ -181,8 +180,8 @@ char placemove(PLAYER *pla,int *move, COMPANY *co, int turn,char *map, int Diffi
if (locs[dir]== STAR) moveval[mvop]=moveval[mvop]+STARCOST ; if (locs[dir]== STAR) moveval[mvop]=moveval[mvop]+STARCOST ;
if (locs[dir]== BLACKHOLE) moveval[mvop]=moveval[mvop]+BLACKHOLECOST ; if (locs[dir]== BLACKHOLE) moveval[mvop]=moveval[mvop]+BLACKHOLECOST ;
if (locs[dir]== NEWCO) { if (locs[dir]== NEWCO) {
moveval[mvop]=moveval[mvop]+NEWCOCOST ; moveval[mvop]=moveval[mvop]+NEWCOCOST ;
} }
if iscompany(locs[dir]) { if iscompany(locs[dir]) {
nc=locs[dir]-'A'; nc=locs[dir]-'A';
if ((ncom==0)||(nc!=neighb[1])){ if ((ncom==0)||(nc!=neighb[1])){
@ -193,20 +192,20 @@ char placemove(PLAYER *pla,int *move, COMPANY *co, int turn,char *map, int Diffi
} }
if (ncom==0) if (moveval[mvop]>100) moveval[mvop]*=FOUNDER_BONUS; else moveval[mvop]=0 ; if (ncom==0) if (moveval[mvop]>100) moveval[mvop]*=FOUNDER_BONUS; else moveval[mvop]=0 ;
/*need to check here whether company eliminated by black hole */ /*need to check here whether company eliminated by black hole */
else if (ncom==1){ else if (ncom==1){
/*if company next door and holding is minimal then value will be reversed*/ /*if company next door and holding is minimal then value will be reversed*/
moveval[mvop]=moveval[mvop]*( coholdings[neighb[1]]-0.25)*tothold[ncom]; moveval[mvop]=moveval[mvop]*( coholdings[neighb[1]]-0.25)*tothold[ncom];
} }
else if (ncom>1){ else if (ncom>1){
/*calculate value of merger*/ /*calculate value of merger*/
smallC=1; smallC=1;
bigC=1; bigC=1;
for (curCo=2;curCo<=ncom;curCo++){ for (curCo=2;curCo<=ncom;curCo++){
if (co[neighb[curCo]].price<co[neighb[smallC]].price) if (co[neighb[curCo]].price<co[neighb[smallC]].price)
smallC= curCo; smallC= curCo;
if (co[neighb[curCo]].price>co[neighb[bigC]].price) if (co[neighb[curCo]].price>co[neighb[bigC]].price)
bigC= curCo; bigC= curCo;
} }
sgain=co[neighb[smallC]].price*tothold[neighb[smallC]]* sgain=co[neighb[smallC]].price*tothold[neighb[smallC]]*
(coholdings[neighb[smallC]]-0.25)/2;/*bonus*/ (coholdings[neighb[smallC]]-0.25)/2;/*bonus*/
sgain+=co[bigC].price*tothold[neighb[smallC]]* sgain+=co[bigC].price*tothold[neighb[smallC]]*
@ -214,7 +213,7 @@ char placemove(PLAYER *pla,int *move, COMPANY *co, int turn,char *map, int Diffi
bgain=(moveval[mvop]+co[neighb[smallC]].price)* bgain=(moveval[mvop]+co[neighb[smallC]].price)*
tothold[neighb[bigC]]*(coholdings[neighb[bigC]]-0.25); tothold[neighb[bigC]]*(coholdings[neighb[bigC]]-0.25);
moveval[mvop]=sgain+bgain; moveval[mvop]=sgain+bgain;
} }
if (moveval[mvop]>curMax) { if (moveval[mvop]>curMax) {
intchar= mvop +(int)'1'; intchar= mvop +(int)'1';
@ -227,8 +226,8 @@ char placemove(PLAYER *pla,int *move, COMPANY *co, int turn,char *map, int Diffi
} }
/* /*
** distantblackhole starts at the black hole, moves two away and then ** distantblackhole starts at the black hole, moves two away and then
** looks at the three ajacent points for companies. It then increases ** looks at the three ajacent points for companies. It then increases
** the risk factor for any companies found. It isn't ** the risk factor for any companies found. It isn't
** always able to detect when the route between the black hole ** always able to detect when the route between the black hole
@ -240,7 +239,7 @@ void distantblackhole(COMPANY *co,char *map,int loc)
int step,cloc; int step,cloc;
enum compass dir,end; enum compass dir,end;
int neighb[4], ncom, new,isnew,curCo; int neighb[4], ncom, new,isnew,curCo;
for (dir=North;dir<=South;dir++){ for (dir=North;dir<=South;dir++){
step =onestep(dir, loc); step =onestep(dir, loc);
if (step>-1) if (map[step]==SPACE){ if (step>-1) if (map[step]==SPACE){
@ -251,7 +250,7 @@ void distantblackhole(COMPANY *co,char *map,int loc)
cloc= onestep(end, step); cloc= onestep(end, step);
if iscompany(map[cloc]) { if iscompany(map[cloc]) {
new=map[cloc]-'A'; new=map[cloc]-'A';
isnew=1; isnew=1;
curCo=0; curCo=0;
while ((curCo<=ncom) && (isnew==1)){ while ((curCo<=ncom) && (isnew==1)){
if (curCo==ncom) /* no need to check if co already found if first */ if (curCo==ncom) /* no need to check if co already found if first */
@ -266,32 +265,32 @@ void distantblackhole(COMPANY *co,char *map,int loc)
} }
} }
curCo=1; curCo=1;
while (curCo<=ncom){ while (curCo<=ncom){
co[neighb[curCo]].risk+= BLACKHOLECOST/2; co[neighb[curCo]].risk+= BLACKHOLECOST/2;
curCo++; curCo++;
} }
} }
} }
} }
/* /*
**ai_buy_sell not only choses the most promising investments but **ai_buy_sell not only choses the most promising investments but
**actually executes the sales **actually executes the sales
*/ */
void ai_buy_sell(PLAYER *pl, COMPANY *co, int turn,char *map, int Difficulty) void ai_buy_sell(PLAYER *pl, COMPANY *co, int turn,char *map, int Difficulty)
{ {
int curloc,curCo,BuyCo,SecCo,amt ; int curloc,curCo,BuyCo,SecCo,amt ;
static int MAPX=Mx , MAPY=My; static int MAPX=Mx , MAPY=My;
int localpt, localris; int localpt, localris;
enum compass dir; enum compass dir;
int neighb[4]; int neighb[4];
int nc, ncom,smallC,bigC; int nc, ncom,smallC,bigC;
char locs[South]; char locs[South];
for(curCo=0;curCo<NUMCO;curCo++) { /*reset values*/ for(curCo=0;curCo<NUMCO;curCo++) { /*reset values*/
co[curCo].potential=co[curCo].risk=0; co[curCo].potential=co[curCo].risk=0;
} }
for (curloc=1;curloc<=(Mx*My);curloc++){ for (curloc=1;curloc<=(Mx*My);curloc++){
if (map[curloc]==BLACKHOLE) distantblackhole(co,map,curloc); if (map[curloc]==BLACKHOLE) distantblackhole(co,map,curloc);
if (map[curloc]==SPACE);{ if (map[curloc]==SPACE);{
@ -299,12 +298,12 @@ void ai_buy_sell(PLAYER *pl, COMPANY *co, int turn,char *map, int Difficulty)
locs[South] = down_obj(curloc); locs[South] = down_obj(curloc);
locs[West] = left_obj(curloc); locs[West] = left_obj(curloc);
locs[East] = right_obj(curloc); locs[East] = right_obj(curloc);
localris=0; localris=0;
localpt=NEWCOCOST; /*the gain from the point itself */ localpt=NEWCOCOST; /*the gain from the point itself */
for(dir=North;dir<=South;dir++){ for(dir=North;dir<=South;dir++){
if (locs[dir]== STAR) localpt=localpt+STARCOST ;/*First check the value or */ if (locs[dir]== STAR) localpt=localpt+STARCOST ;/*First check the value or */
if ((Difficulty>2 )||(rand()%100>50)) if ((Difficulty>2 )||(rand()%100>50))
if (locs[dir]== BLACKHOLE) if (locs[dir]== BLACKHOLE)
localris=localris+BLACKHOLECOST;/*loss from the point*/ localris=localris+BLACKHOLECOST;/*loss from the point*/
if (locs[dir]== NEWCO) localpt=localpt+NEWCOCOST ; if (locs[dir]== NEWCO) localpt=localpt+NEWCOCOST ;
} }
@ -319,63 +318,63 @@ void ai_buy_sell(PLAYER *pl, COMPANY *co, int turn,char *map, int Difficulty)
} }
} }
} }
if (ncom==1 ){ if (ncom==1 ){
co[nc].potential=co[nc].potential+localpt; co[nc].potential=co[nc].potential+localpt;
co[nc].risk=co[nc].risk+localris; co[nc].risk=co[nc].risk+localris;
} }
else if (ncom>1){ else if (ncom>1){
smallC=1; smallC=1;
bigC=1; bigC=1;
for (curCo=2;curCo<=ncom;curCo++){ for (curCo=2;curCo<=ncom;curCo++){
if (co[neighb[curCo]].price<co[neighb[smallC]].price) if (co[neighb[curCo]].price<co[neighb[smallC]].price)
smallC= curCo; smallC= curCo;
if (co[neighb[curCo]].price>co[neighb[bigC]].price) if (co[neighb[curCo]].price>co[neighb[bigC]].price)
bigC= curCo; bigC= curCo;
} }
/* bonus ignored for now*/ /* bonus ignored for now*/
co[neighb[bigC]].potential=co[neighb[bigC]].potential+(co[neighb[smallC]].price); co[neighb[bigC]].potential=co[neighb[bigC]].potential+(co[neighb[smallC]].price);
co[neighb[smallC]].potential=co[neighb[smallC]].potential+co[neighb[bigC]].price/2; co[neighb[smallC]].potential=co[neighb[smallC]].potential+co[neighb[bigC]].price/2;
} }
} }
SecCo=BuyCo=-1 ; SecCo=BuyCo=-1 ;
for(curCo=0;curCo<NUMCO;curCo++) /*Find the co with greatest potential*/ for(curCo=0;curCo<NUMCO;curCo++) /*Find the co with greatest potential*/
if (co[curCo].price>0) { if (co[curCo].price>0) {
co[curCo].netpot=(co[curCo].potential+co[curCo].risk)/ co[curCo].netpot=(co[curCo].potential+co[curCo].risk)/
(co[curCo].price); (co[curCo].price);
if ((co[curCo].netpot>0)){ if ((co[curCo].netpot>0)){
if (BuyCo==-1) BuyCo=curCo; if (BuyCo==-1) BuyCo=curCo;
else { else {
if (co[curCo].netpot>co[BuyCo].netpot) { if (co[curCo].netpot>co[BuyCo].netpot) {
SecCo=BuyCo; SecCo=BuyCo;
BuyCo=curCo; BuyCo=curCo;
} }
else { else {
if (SecCo==-1) SecCo=curCo; if (SecCo==-1) SecCo=curCo;
else if (co[curCo].netpot>co[SecCo].netpot) else if (co[curCo].netpot>co[SecCo].netpot)
SecCo=curCo; SecCo=curCo;
} }
} }
} }
} }
if ((Difficulty>2 )||((Difficulty>1 )&&(rand()%100>50)) ) if ((Difficulty>2 )||((Difficulty>1 )&&(rand()%100>50)) )
for(curCo=0;curCo<NUMCO;curCo++){ /*sell all*/ for(curCo=0;curCo<NUMCO;curCo++){ /*sell all*/
pl[turn].cash += pl[turn].holdings[curCo]*co[curCo].price; pl[turn].cash += pl[turn].holdings[curCo]*co[curCo].price;
pl[turn].holdings[curCo]=0; pl[turn].holdings[curCo]=0;
} }
if (BuyCo>-1){ /*now buy shares in the company with the best prospects*/ if (BuyCo>-1){ /*now buy shares in the company with the best prospects*/
if (co[BuyCo].risk<0) { /*don't put all your eggs into one basket*/ if (co[BuyCo].risk<0) { /*don't put all your eggs into one basket*/
amt= pl[turn].cash/(co[BuyCo].price*2); amt= pl[turn].cash/(co[BuyCo].price*2);
pl[turn].cash += (-amt * co[BuyCo].price); pl[turn].cash += (-amt * co[BuyCo].price);
pl[turn].holdings[BuyCo] += amt; pl[turn].holdings[BuyCo] += amt;
if (SecCo>-1){ if (SecCo>-1){
amt= pl[turn].cash/co[SecCo].price; amt= pl[turn].cash/co[SecCo].price;
pl[turn].cash += (-amt * co[SecCo].price); pl[turn].cash += (-amt * co[SecCo].price);
pl[turn].holdings[SecCo] += amt; pl[turn].holdings[SecCo] += amt;
} }
} }
else { else {
amt= pl[turn].cash/co[BuyCo].price; amt= pl[turn].cash/co[BuyCo].price;
pl[turn].cash += (-amt * co[BuyCo].price); pl[turn].cash += (-amt * co[BuyCo].price);
pl[turn].holdings[BuyCo] += amt; pl[turn].holdings[BuyCo] += amt;
} }

View File

@ -1,3 +1,17 @@
Version 1.4.2 released 2020 by ~creme
creme@envs.net
change company names to default
Version 1.4.1 released 2020 by ~creme
creme@envs.net
change game-settings to default
Version 1.4.0 released 2020 by ~jan6 Version 1.4.0 released 2020 by ~jan6
jan6@tilde.ninja and jan6@envs.net jan6@tilde.ninja and jan6@envs.net
@ -15,7 +29,7 @@ Stripped the binary (about halving final size)
Version 1.3.0 released 2004 by David Barnsdale Version 1.3.0 released 2004 by David Barnsdale
dejvid@barnsdle.demon.co.uk and dejvid@zamir.net dejvid@barnsdle.demon.co.uk and dejvid@zamir.net
AI implemented. All AI related stuff placed in "ai.c". AI implemented. All AI related stuff placed in "ai.c".

View File

@ -3,34 +3,34 @@
** modify it under the terms of the GNU General Public License ** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2 ** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version. ** of the License, or (at your option) any later version.
** **
** This program is distributed in the hope that it will be useful, ** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License v2 for more details. ** GNU General Public License v2 for more details.
** **
** You should have received a copy of the GNU General Public License ** You should have received a copy of the GNU General Public License
** along with this program; ** along with this program;
*/ */
#define OFFMAP '-' /* space character */ #define OFFMAP '-' /* space character */
#define SPACE '.' /* space character */ #define SPACE '.' /* space character */
#define NEWCO '+' /* new company character */ #define NEWCO '+' /* new company character */
#define STAR '*' /* star character */ #define STAR '*' /* star character */
#define BLACKHOLE '@' /* black hole character */ #define BLACKHOLE '@' /* black hole character */
#define NUMCO 5 /* number of companies (don't change) */ #define NUMCO 5 /* number of companies (don't change) */
#define INIT_CO_COST 90 /* initial company start cost */ #define INIT_CO_COST 100 /* initial company start cost */
#define FOUNDER_BONUS 10 /* founder gets this much stock */ #define FOUNDER_BONUS 5 /* founder gets this much stock */
#define NUMMOVES 6 /* number of moves options a player gets */ #define NUMMOVES 5 /* number of moves options a player gets */
#define MAXPLAYERS 4 /* total number of players a game can have */ #define MAXPLAYERS 4 /* total number of players a game can have */
#define STARCOST 251 /* company's price increase near star */ #define STARCOST 500 /* company's price increase near star */
#define BLACKHOLECOST -250 /* price increase near black hole */ #define BLACKHOLECOST -500 /* price increase near black hole */
#define NEWCOCOST 101 /* company's price increase near new co */ #define NEWCOCOST 100 /* company's price increase near new co */
#define Mx 12 /* x dimension of map */ #define Mx 12 /* x dimension of map */
#define My 10 /* y dimension of map */ #define My 10 /* y dimension of map */
/* macros to look at surrounding spaces on the map: */ /* macros to look at surrounding spaces on the map: */
@ -42,8 +42,6 @@
/* player and company structures: */ /* player and company structures: */
typedef struct { typedef struct {
@ -62,3 +60,4 @@ typedef struct {
int risk; /* value related to chance of being swallowed by Black Hole */ int risk; /* value related to chance of being swallowed by Black Hole */
int netpot; /* potential - risk */ int netpot; /* potential - risk */
} COMPANY; } COMPANY;
MPANY;

View File

@ -1,8 +1,8 @@
.TH STARLANES 6 "29 March 1996" "Starlanes V1.2.2" .TH STARLANES 6 "12 February 2020" "Starlanes V1.4.2"
.SH NAME .SH NAME
starlanes \- the game of starlanes starlanes \- the game of starlanes
.SH SYNOPSIS .SH SYNOPSIS
.BR "starlanes " [ -v | c | m ] .BR "starlanes " [ -v | c | m ]
.SH DESCRIPTION .SH DESCRIPTION
.B Starlanes .B Starlanes
is a game of interstellar commerce for 1 to 4 players. Players take is a game of interstellar commerce for 1 to 4 players. Players take

View File

@ -1,19 +1,19 @@
/* /*
** starlanes v1.3.0 (29-Mar-1997) -- a space-age stock trading game ** starlanes v1.4.2 (12-Feb-2020) -- a space-age stock trading game
** **
** Copyright (C) 1997 Brian "Beej" Hall ** Copyright (C) 1997 Brian "Beej" Hall
** with modifications by David Barnsdale 2004 and by ~jan6 2020 ** with modifications by David Barnsdale 2004 and by ~jan6 2020
** **
** This program is free software; you can redistribute it and/or ** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License ** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2 ** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version. ** of the License, or (at your option) any later version.
** **
** This program is distributed in the hope that it will be useful, ** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details. ** GNU General Public License for more details.
** **
** You should have received a copy of the GNU General Public License ** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software ** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@ -30,7 +30,7 @@
#include <unistd.h> #include <unistd.h>
#include <ncurses.h> #include <ncurses.h>
#include <termios.h> #include <termios.h>
#include "common.h" #include "common.h"
@ -101,7 +101,7 @@
/* #define NUMMOVES 5 number of different moves a player gets */ /* #define NUMMOVES 5 number of different moves a player gets */
#define END_PERCENT 55 /* end when this much of the map is full */ #define END_PERCENT 54 /* end when this much of the map is full */
#define DEF_LINES 25 /* default number of lines on screen */ #define DEF_LINES 25 /* default number of lines on screen */
#define DEF_COLUMNS 80 /* default number of columns on screen */ #define DEF_COLUMNS 80 /* default number of columns on screen */
@ -161,8 +161,8 @@ void usage(void);
char placemove(); */ char placemove(); */
/* global variables */ /* global variables */
char *VERSION = "1.3.0"; char *VERSION = "1.4.2";
char *VERSION_DATE = "1-June-2004"; char *VERSION_DATE = "12-February-2020";
char *ident = "$Id: starlanes.c 1.2.2 29-Mar-1997 beej@ecst.csuchico.edu $"; char *ident = "$Id: starlanes.c 1.2.2 29-Mar-1997 beej@ecst.csuchico.edu $";
@ -210,7 +210,7 @@ int main(int argc, char *argv[])
/* initscr */ /* initscr */
initscr(); initscr();
start_color(); start_color();
if (colorforce) if (colorforce)
color = 1; color = 1;
else if (monoforce) else if (monoforce)
@ -228,7 +228,7 @@ int main(int argc, char *argv[])
/* num players */ /* num players */
get_num_players(); get_num_players();
clear(); clear();
attron(color?(YELLOW_ON_BLUE|A_BOLD):A_REVERSE); attron(color?(YELLOW_ON_BLUE|A_BOLD):A_REVERSE);
mvprintw(0,0," StarLanes "); mvprintw(0,0," StarLanes ");
@ -314,11 +314,11 @@ void initialize(void)
for(i=0;i<NUMCO;i++) { for(i=0;i<NUMCO;i++) {
switch(i) { switch(i) {
case 0: strcpy(co[i].name, "Altar & Stairway, Ltd.");break; case 0: strcpy(co[i].name, "Altair Starways");break;
case 1: strcpy(co[i].name, "Beatles & Juice Co.");break; case 1: strcpy(co[i].name, "Beetlejuice, Ltd.");break;
case 2: strcpy(co[i].name, "Capella Fright, Ltd.");break; case 2: strcpy(co[i].name, "Capella Freight Co.");break;
case 3: strcpy(co[i].name, "Denebola Dice Shippers");break; case 3: strcpy(co[i].name, "Denebola Shippers");break;
case 4: strcpy(co[i].name, "Eridani Expert Export");break; case 4: strcpy(co[i].name, "Eridani Expediters");break;
} }
co[i].size = co[i].price = 0; co[i].size = co[i].price = 0;
} }
@ -416,9 +416,9 @@ void get_num_players(void)
/* if (numplayers == 0){ /* if (numplayers == 0){
numplayers=4; numplayers=4;
sologame=1; sologame=1;
sprintf(s,"Please enter level (1 easiest,3 hardest)"); sprintf(s,"Please enter level (1 easiest,3 hardest)");
center(stdscr,COLUMNS ,11,s); center(stdscr,COLUMNS ,11,s);
refresh(); refresh();
noecho();raw(); noecho();raw();
do { do {
Difficulty = getch()-'0'; Difficulty = getch()-'0';
@ -426,7 +426,7 @@ void get_num_players(void)
addch(Difficulty+'0'); addch(Difficulty+'0');
} }
else */ sologame=0; else */ sologame=0;
srand(getpid()); /* reseed the dumb random number generator */ srand(getpid()); /* reseed the dumb random number generator */
turn = rand()%numplayers; turn = rand()%numplayers;
@ -443,12 +443,12 @@ void get_num_players(void)
my_mvwgetstr(stdscr,plnmr+12+sologame,49,20,0,pl[plnmr].name); my_mvwgetstr(stdscr,plnmr+12+sologame,49,20,0,pl[plnmr].name);
/*getstr(pl[plnmr].name);*/ /*getstr(pl[plnmr].name);*/
if (pl[plnmr].name[0] == '\0') plnmr--; if (pl[plnmr].name[0] == '\0') plnmr--;
// } // }
} }
nonl(); nonl();
} }
/* /*
** showmap() -- draws the map in the map window ** showmap() -- draws the map in the map window
*/ */
@ -562,10 +562,10 @@ void show_coinfo(void)
int get_move(void) int get_move(void)
{ {
char s[80],c; char s[80],c;
int move[NUMMOVES],i,j,ok,splat; int move[NUMMOVES],i,j,ok,splat;
/* move[] is the numbered options that are shown on the screen /* move[] is the numbered options that are shown on the screen
i represents each of the random place points while j i represents each of the random place points while j
represents the already chosen points which must be represents the already chosen points which must be
checked to avoid duplicates. */ checked to avoid duplicates. */
wattron(mapwin,A_REVERSE); wattron(mapwin,A_REVERSE);
@ -725,7 +725,7 @@ void do_move(int move)
calc_cost(newc_type-'A',move,north,south,west,east); calc_cost(newc_type-'A',move,north,south,west,east);
if (co[newc_type-'A'].price <= 0) /* black holed */ if (co[newc_type-'A'].price <= 0) /* black holed */
suck_announce(newc_type-'A',1); suck_announce(newc_type-'A',1);
else { else {
if (co[newc_type-'A'].price > SPLIT_PRICE) if (co[newc_type-'A'].price > SPLIT_PRICE)
split_announce(newc_type-'A'); split_announce(newc_type-'A');
else else
@ -764,7 +764,7 @@ void do_merge(int *c1, int *c2, int *o1, int *o2)
cb = t; cb = t;
} }
for(i=0;i<MAPX*MAPY;i++) for(i=0;i<MAPX*MAPY;i++)
if (map[i] == cs+'A') { if (map[i] == cs+'A') {
map[i] = cb+'A'; map[i] = cb+'A';
drawmap(i,cb+'A'); drawmap(i,cb+'A');
@ -777,7 +777,7 @@ void do_merge(int *c1, int *c2, int *o1, int *o2)
co[cb].size += co[cs].size; co[cb].size += co[cs].size;
co[cb].price += co[cs].price; co[cb].price += co[cs].price;
co[cs].size = 0; co[cs].size = 0;
wnoutrefresh(mapwin); /* show the players what's up */ wnoutrefresh(mapwin); /* show the players what's up */
merge_announce(cb,cs); merge_announce(cb,cs);
@ -802,7 +802,7 @@ void calc_cost(int cnum, int move, int n, int s, int w, int e)
if (s == BLACKHOLE) co[cnum].price += BLACKHOLECOST; if (s == BLACKHOLE) co[cnum].price += BLACKHOLECOST;
if (w == BLACKHOLE) co[cnum].price += BLACKHOLECOST; if (w == BLACKHOLE) co[cnum].price += BLACKHOLECOST;
if (e == BLACKHOLE) co[cnum].price += BLACKHOLECOST; if (e == BLACKHOLE) co[cnum].price += BLACKHOLECOST;
if (n == NEWCO) { /* starter companies */ if (n == NEWCO) { /* starter companies */
map[move-MAPX] = cnum + 'A'; /*company represented by A is 0 and so on */ map[move-MAPX] = cnum + 'A'; /*company represented by A is 0 and so on */
drawmap(move-MAPX,cnum+'A'); drawmap(move-MAPX,cnum+'A');
@ -867,7 +867,7 @@ void suck_announce(int conum, int grown)
} }
} }
wnoutrefresh(mapwin); wnoutrefresh(mapwin);
for(i=0;i<numplayers;i++) /* ditch all player holdings */ for(i=0;i<numplayers;i++) /* ditch all player holdings */
pl[i].holdings[conum] = 0; pl[i].holdings[conum] = 0;
@ -985,7 +985,7 @@ void split_announce(int conum)
center(general,COLUMNS-2,6,"Press any key to continue..."); center(general,COLUMNS-2,6,"Press any key to continue...");
co[conum].price = (int)(((float)(co[conum].price)/2.0) + 0.5); co[conum].price = (int)(((float)(co[conum].price)/2.0) + 0.5);
for(i=0;i<numplayers;i++) for(i=0;i<numplayers;i++)
pl[i].holdings[conum] *= 2; pl[i].holdings[conum] *= 2;
show_coinfo(); show_coinfo();
@ -1181,7 +1181,7 @@ int count_used_sectors(void)
for(i=maptotal=0;i<MAPX*MAPY;i++) /* must be enough room to move */ for(i=maptotal=0;i<MAPX*MAPY;i++) /* must be enough room to move */
if (map[i] != SPACE) if (map[i] != SPACE)
maptotal++; maptotal++;
return maptotal; return maptotal;
} }
@ -1374,7 +1374,7 @@ int order_compare(const void *v1, const void *v2)
p1 = *((int *)v1); p1 = *((int *)v1);
p2 = *((int *)v2); p2 = *((int *)v2);
nw1 = pl[p1].svalue + pl[p1].cash; nw1 = pl[p1].svalue + pl[p1].cash;
nw2 = pl[p2].svalue + pl[p2].cash; nw2 = pl[p2].svalue + pl[p2].cash;
@ -1500,10 +1500,10 @@ void show_company_holdings(char *title)
wprintw(stand,"%-5d %-5d ",pl[order[plNo]].holdings[1],pl[order[plNo]].holdings[2]); wprintw(stand,"%-5d %-5d ",pl[order[plNo]].holdings[1],pl[order[plNo]].holdings[2]);
wprintw(stand,"%-5d %-5d",pl[order[plNo]].holdings[3],pl[order[plNo]].holdings[4]); wprintw(stand,"%-5d %-5d",pl[order[plNo]].holdings[3],pl[order[plNo]].holdings[4]);
} }
center(stand,60,5+numplayers, s); center(stand,60,5+numplayers, s);
center(stand,60,7+numplayers,"Press any key to continue..."); center(stand,60,7+numplayers,"Press any key to continue...");
wnoutrefresh(stand); wnoutrefresh(stand);
@ -1564,7 +1564,7 @@ void shutdown(void)
printf("Starlanes for ncurses v%s Copyright by Brian \"Beej\" Hall 1997 \n",VERSION); printf("Starlanes for ncurses v%s Copyright by Brian \"Beej\" Hall 1997 \n",VERSION);
printf("Update: David Barnsdale 2004\n"); printf("Update: David Barnsdale 2004\n");
printf("Update: jan6 2020\n"); printf("Update: jan6 2020\n");
} }
/* /*

View File

@ -391,6 +391,6 @@ BUGS
Starlanes V1.2.2 29 March 1996 6 Starlanes V1.4.2 12 February 2020 6