fixup for HEAD^2
[rofl0r-financial-time-machine.git] / ftm.c
blob996a8c6812d4331b36166b76c1bc59bde7bd85cf
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4 #include <math.h>
5 #include <sys/time.h>
6 #include <unistd.h>
7 #include <assert.h>
8 #include <stdarg.h>
9 #include "amiga.h"
10 #include "ezsdl.h"
12 #ifdef DEBUG
13 #define DPRINTF(...) dprintf(2, __VA_ARGS__)
14 #else
15 #define DPRINTF(...) do { } while(0)
16 #endif
18 #define SCALE 2
19 #define SU(x) ((x)*SCALE)
20 #define ARRAY_SIZE(X) (sizeof(X)/sizeof(X[0]))
22 #define cursor(X,Y) cursorit(X,Y,__FUNCTION__, __LINE__)
23 #define Move(X,Y,Z) Moveit(X,Y,Z,__FUNCTION__, __LINE__)
25 #define vmode vmodeitt
26 #define getkb getkbitt
28 #define NONE 0
29 #define NOT_FOUND -1
30 #define COMMAND 1
31 #define STOCK 2
32 #define ALL -2
34 #define BONDVALUE 1000
35 #define STOCKLIMIT 9 /* max number of stocks one can hold */
36 #define AUTOLIMIT 9 /* max number of autos and options */
38 #define SPLITPRICE 200
39 #define GAMMA1 1.5
40 #define GAMMA2 .3
41 #define GAMMA3 .3
43 #define TRUE 1
44 #define FALSE 0
45 #define ESC '\033'
46 #define CR 13
47 #define BACKSP '\010'
48 #define BREAK '\t'
49 #define BEEP '\07'
50 #define ERASE_CH "'\08' '\08'"
52 #define AUTOBUY 20
53 #define AUTOSELL 21
54 #define NON_AUTO 1
55 #define ON 1
56 #define OFF 2
57 #define CHANGEOVERTIME 10 /* 10 seconds to complete command */
58 #define CLICK_CHANGE '\021'
59 #define NO_YRLY_MESSAGES 15
60 #define NO_STD_MESSAGES 30
61 #define YRLY 0
62 #define STD 1
63 #define GOLD 26
64 #define REALESTATE 25
65 #define MMMS 30
66 #define WEEKLENGTH 25
67 #define DIFFERENCE 48
68 #define STOCKSUP 1
69 #define AUTOSUP 2
70 #define RANKINGSUP 3
71 #define GRAPHUP 4
73 #define MAXPLAYERS 4
74 #define LOTLIMIT 9999
75 #define TICK_SIZE 3
76 #define LONG 1
77 #define SHORT 0
80 #define F10 -80 /** for JUMPing. Added 11/22/85 **/
82 #define SCREENH 240
83 #define SCREENW 320
85 static bmp4*bmp_font, *bmp_black_font;
86 static struct spritesheet ss_font, ss_black_font;
88 #define BOTTOM_START 76
89 #define FONT "topaz.raw"
90 #define FONT_W 8
91 #define FONT_H 8
92 static void init_gfx() {
93 bmp_font = bmp4_from_file(FONT);
94 bmp_black_font = bmp4_from_file(FONT);
95 unsigned x;
96 for(x=0;x<bmp_black_font->width * bmp_black_font->height;x++)
97 bmp_black_font->data[x] = bmp_black_font->data[x] == RGB(0,0,0) ? RGB(255,255,255) : RGB(0,0,0);
98 if(!spritesheet_init(&ss_font, bmp_font, FONT_W, FONT_H)) dprintf(2, "oops\n");
99 if(!spritesheet_init(&ss_black_font, bmp_black_font, FONT_W, FONT_H)) dprintf(2, "oops\n");
102 static int get_font_width(char letter) {
103 return ss_font.sprite_w;
106 static unsigned get_font_render_length(const char* text) {
107 unsigned x=0;
108 for(;*text && *text != '\n';x+=get_font_width(*(text++)));
109 return x;
112 static void draw_font(const char* text, struct spritesheet *font, unsigned x, unsigned y) {
113 for(;*text;x+=get_font_width(*(text++))) if(*text != '\n') ezsdl_draw_sprite(font, *text, SU(x), SU(y), SCALE);
116 typedef struct stock {
117 char name[4];
118 float b1;
119 float b2;
120 float b3;
121 float e;
122 int price;
123 } ASTOCK;
125 typedef struct {
126 int price[20];
127 char splits[20];
128 } HISTORY;
130 static ASTOCK stock_array[] = {
131 [ 0] = {.price = 100, .name = "KM", .b1 = 1.4, .b2 = .8, .b3 = 0, .e = .2},
132 [ 1] = {.price = 100, .name = "GE", .b1 = 1.3, .b2 = .4, .b3 = -.2, .e = .3},
133 [ 2] = {.price = 100, .name = "AMR", .b1 = 2.1, .b2 = .9, .b3 = .2, .e = .5},
134 [ 3] = {.price = 100, .name = "ZE", .b1 = 1.7, .b2 = .0, .b3 = 0, .e = .5},
135 [ 4] = {.price = 100, .name = "MYG", .b1 = 1.4, .b2 = .5, .b3 = 0, .e = .3},
136 [ 5] = {.price = 100, .name = "GM", .b1 = 1.3, .b2 = .8, .b3 = .3, .e = .2},
137 [ 6] = {.price = 100, .name = "SOI", .b1 = 1., .b2 = .4, .b3 = -.3, .e = .3},
138 [ 7] = {.price = 100, .name = "USS", .b1 = 1.1, .b2 = .6, .b3 = 0, .e = .3},
139 [ 8] = {.price = 100, .name = "ITT", .b1 = 1.6, .b2 = .0, .b3 = 0, .e = 1.2},
140 [ 9] = {.price = 100, .name = "MOB", .b1 = .9, .b2 = .2, .b3 = .8, .e = .2},
141 [10] = {.price = 100, .name = "PG", .b1 = .85, .b2 = .3, .b3 = 0, .e = 1.2},
142 [11] = {.price = 100, .name = "EK", .b1 = 1.2, .b2 = 0., .b3 = 0, .e = .4},
143 [12] = {.price = 100, .name = "AH", .b1 = 1., .b2 = 1., .b3 = .2, .e = .3},
144 [13] = {.price = 100, .name = "KMB", .b1 = .7, .b2 = .1, .b3 = 0, .e = .1},
145 [14] = {.price = 100, .name = "DE", .b1 = 1.3, .b2 = 1.3, .b3 = 0, .e = .4},
146 [15] = {.price = 100, .name = "ED", .b1 = .65, .b2 = 1.1, .b3 = 0, .e = .1},
147 [16] = {.price = 100, .name = "AA", .b1 = 1.7, .b2 = 1.2, .b3 = .1, .e = .3},
148 [17] = {.price = 100, .name = "PGL", .b1 = .2, .b2 = 0., .b3 = -.4, .e = 1.5},
149 [18] = {.price = 100, .name = "MD", .b1 = 2., .b2 = .2, .b3 = -.5, .e = .8},
150 [19] = {.price = 100, .name = "T", .b1 = 1.2, .b2 = 0., .b3 = 0., .e = .7},
151 [20] = {.price = 100, .name = "MTC", .b1 = 1., .b2 = .2, .b3 = 0, .e = .4},
152 [21] = {.price = 100, .name = "UNP", .b1 = 1.7, .b2 = 1.4, .b3 = 0, .e = .9},
153 [22] = {.price = 100, .name = "HM", .b1 = -.2, .b2 = .3, .b3 = -.5, .e = .8},
154 [23] = {.price = 100, .name = "SMC", .b1 = 2.2, .b2 = 1.4, .b3 = 0, .e = 1.1},
155 [24] = {.price = 100, .name = "NOM", .b1 = 1.3, .b2 = 1., .b3 = -.3, .e = 1.6},
156 [25] = {.price = 100, .name = "RES", .b1 = .05, .b2 = .9, .b3 = 0, .e = .25},
157 [26] = {.price = 100, .name = "GLD", .b1 = -.1, .b2 = 1.1, .b3 = -.3, .e = .6},
158 [27] = {.price = 100, .name = "WU", .b1 = -.2, .b2 = -.4, .b3 = 0, .e = .6},
159 [28] = {.price = 100, .name = "BND", .b1 = .05, .b2 = .7, .b3 = 0, .e = .0},
160 [29] = {.price = 100, .name = "IBM", .b1 = .9, .b2 = .3, .b3 = 1.2, .e = .6},
161 [30] = {.price = 100, .name = "IMF", .b1 = .0, .b2 = .0, .b3 = 0, .e = .0},
164 #define NO_OF_STOCKS ARRAY_SIZE(stock_array)
165 static HISTORY history[NO_OF_STOCKS];
167 static char alpha[] =
168 { 16, 12, 2, 28, 14, 15, 11, 1, 26, 5, 22, 29, 8, 0, 13, 18, 9, 20, 4, 24, 10, 17, 25, 23, 6, 19, 21, 7, 27, 3, 30 };
170 typedef struct {
171 int stock_no;
172 int units;
173 int price;
174 float margin_debt;
175 } SCREEN;
177 static SCREEN screen[STOCKLIMIT];
178 static SCREEN *scr_ptr[STOCKLIMIT];
179 static int screen_count;
181 typedef struct {
182 char string[82];
183 float intr;
184 float gnp;
185 float pol;
186 float var;
187 char used;
189 } YMESS;
191 typedef struct {
192 YMESS item[NO_YRLY_MESSAGES];
193 } YMESSS;
195 static YMESSS yrly_mssgs;
197 static int y_mssg_count;
199 typedef struct {
200 char string[82];
201 float intr;
202 float gnp;
203 float pol;
204 float var;
206 } SMESS;
208 typedef struct {
209 SMESS item[NO_STD_MESSAGES];
210 } SMESSS;
212 static SMESSS std_mssgs;
214 #define JUMP 13
215 #define LIMIT 12
216 #define EXERCISE 11
217 #define GRAPH 10
218 #define CASH 9
219 #define SAVE 8
220 #define BONDS 7
221 #define MARGIN 6
222 #define QUIT 5
223 #define DELETE 4
224 #define PUT 3
225 #define CALL 2
226 #define SELL 1
227 #define BUY 0
228 static const char commands[][9] = {
229 "BUY",
230 "SELL",
231 "CALL",
232 "PUT",
233 "DELETE",
234 "QUIT",
235 "MARGIN",
236 "BONDS", /* original: "T-BILLS" */
237 "SAVE", /* original "KEEP" */
238 "CASH",
239 "GRAPH",
240 "EXERCISE",
241 "LIMIT",
242 "JUMP"
245 static float ndis[24] = {
247 .53983,
248 .57926,
249 .61791,
250 .65542,
251 .69146,
252 .72575,
253 .75804,
254 .78814,
255 .81594,
256 .84134,
257 .86433,
258 .88493,
259 .90320,
260 .91924,
261 .93319,
262 .94520,
263 .95543,
264 .96407,
265 .97128,
266 .97725,
267 .98214,
268 .98610,
269 .98928
272 typedef struct tick_item {
273 char item[11];
274 struct tick_item *next;
275 struct tick_item *previous;
276 } TICK_ITEM;
278 static TICK_ITEM *cur_tick;
279 static TICK_ITEM ticker[TICK_SIZE];
281 static int load_stock = TICK_SIZE; /* the number of the next stock to be loaded into
282 the ticker. */
284 static char newsline[82]; /* holds current news message */
286 static int cur_news_line = -1; /* the number of the last position in the newline
287 array to be put on screen */
288 typedef struct autos {
289 int minus_price; /* price to exercise auto buy */
290 int plus_price; /* price to exercise auto sell */
291 int option_type; /* CALL or PUT option? */
292 int option_price; /* price option is exerciseable at */
293 int units; /* number of shares */
294 int stock_no; /* stock id number */
295 int cur_price; /* the last price posted */
296 int pur_price; /* how much the option cost per lot */
297 } AUTOS;
300 typedef struct node {
301 int year;
302 int week;
303 int shares;
304 struct node *next;
305 struct node *previous;
306 int price;
307 } NODE;
309 typedef struct {
310 int shares;
311 int limit;
312 float margin_debt;
313 NODE *purchases;
314 } STOCKS;
316 typedef struct player {
317 double cash;
318 double net_worth;
319 STOCKS portfolio[NO_OF_STOCKS];
320 int stock_count;
321 int auto_count;
322 AUTOS *auto_ptr[AUTOLIMIT]; /* pointers to the auto exec structures */
323 AUTOS auto_array[AUTOLIMIT]; /* the actual auto exec structures */
324 char name[21];
325 int name_length; /* characters in the person's name */
326 double taxes;
327 float short_term;
328 float long_term;
329 float other_earnings;
330 int bonds;
332 } PLAYER;
334 static PLAYER players[MAXPLAYERS];
335 static PLAYER *cur_player;
337 typedef struct {
338 int status; /* 1 if ON 2 if OFF */
339 int count; /* seconds since hour when initialized */
340 int hour_changed; /* flag set if timer approaching hour change */
341 } TIMER;
343 static TIMER timer1; /* for game time timing */
344 static TIMER timer2; /* for changing player timing */
345 static TIMER timer3; /* for event gap timing */
347 static char message; /* true if program message displayed */
348 static char scr_status = STOCKSUP; /* either stocks,autos,or rankings are up */
349 static char in_progress; /* in the middle of a news event ? */
350 static char mess_type; /* yearly or standard message in use */
351 static char q_break; /* true at end of quarter */
352 static int no_of_players; /* how many players we have, set at beginning */
353 static int player = 1; /* the current player */
354 static int tmp_player; /* holds the new player while we wait */
355 static float prime_rate = .5; /* actually will be read in initially */
356 static float high_prime; /* highest prime rate allowed */
357 static float low_prime; /* lowest prime rate allowed */
358 static float q_int_rate = .049; /* the quarterly interest rate */
359 static float wk_int_rate = .001; /* quarterly divided by 13 */
360 static float bond_rate; /* quarterly rate at beginning of quarter */
361 static int quarter = 1; /* what the current quarter is */
362 static int week = 1; /* the current week of the year */
363 static int year = 1938; /* actually will be read in initially */
364 static char stop; /* flag to indicate end of quarter break */
365 static int com_char_count; /* how many chars in the buffer */
366 static char delay; /* scroll another news char or not */
367 static char year_over; /* paused at end of year ? */
368 static int event_week = 1; /* the week of the last event */
369 static char com_array[30]; /* holds user input */
370 static int time_count; /* 0 to 3600 replaces real time */
371 static int make_call; /* do a margin call at end of week ? */
373 static float factor1, factor2, factor3, factor4;
374 static float x1, x2, x3, instd1, instd2, instd3, instd4, the_interest, gnp, pol, intr, var;
375 static int weeks;
377 static int jump_weeks; /* number of weeks left in JUMP */
378 /* added: 11/22/85 */
380 static char newsch; /* the next newsline char to scroll */
381 static int units; /* how many to buy,sell,etc. */
382 static int com_no; /* the digit corres. to the command */
383 static int stock_no; /* the number corres. to the stock */
384 static int trans_price; /* the price at which the transaction
385 is to be executed */
386 static int autobuy; /* the price to execute an auto buy */
387 static int autosell; /* the price to execute an auto sell */
388 static int tick_position; /* the position in the current ticker
389 element */
390 static int click_on; /* flag to turn on clicking */
391 static int time; /* current time seconds + minutes */
392 static int messno; /* message selected */
393 static int loop_to; /* when to end the event */
394 static int half_way = -2; /* half thru reset message */
395 static int g; /* junk */
396 static char emphasis;
398 static float vx1, vx2, vx3, vx4; /* variances for option use */
399 //input wave for audio ticker
400 //static signed char si[] = {0,49,90,117,127,117,90,49,0,-49,-90,-117,-127,-117,-90,-49};
402 static struct RastPort *rp;
404 static void save();
405 static void quit(void);
406 static void graph(int stockno, int year);
407 static void bonds(int units);
408 static void add_auto_exec(int auto_minus, int auto_plus, int option, int opt_price, int units, int stockno, int player,
409 int pur_price);
410 static void write_auto(int position);
411 static float opt_value(int player, int position);
412 static void del_auto(int position, int player);
413 static void upd_coh(void);
414 static void upd_netw(void);
415 static void upd_bonds(void);
416 static void upd_quarter(void);
417 static void upd_year(void);
418 static void upd_prime(void);
419 static void upd_stock(int stockno);
420 static void write_stock(int line_inc, int element);
421 static void clear_stock(int line_inc);
422 static void load_screen(void);
423 static void screen_upd(void);
424 static double calc_netw(int player);
426 #define STUB(X) static long X () { dprintf(2, "warning: %s unimplemented\n", __FUNCTION__); return 0;}
428 /* clib/dos_protos.h */
429 static void Delay( long timeout ) {
430 ezsdl_refresh();
431 ezsdl_sleep(timeout*10);
433 /* clib/graphics_protos.h */
434 static void SetDrMd( struct RastPort *rp, unsigned long drawMode ) {
435 rp->DrawMode = drawMode;
437 static void Moveit( struct RastPort *rp, long x, long y, const char*fn, int line ) {
438 #ifdef DEBUG_CALLS
439 dprintf(2, "%s called from %s:%d\n", __FUNCTION__, fn, line);
440 #endif
441 assert(x<SCREENW);
442 assert(y<SCREENH);
443 rp->custom.x = x;
444 rp->custom.y = y;
446 #define MIN(a,b) ((a)<(b)) ? (a) : (b)
447 #define ABS(a) ((a) < 0) ? -(a) : (a)
449 /* Set the primary drawing pen for lines, fills, and text. */
450 static void SetAPen( struct RastPort *rp, unsigned long pen ) {
451 rp->FgPen = pen;
453 /* Set the secondary drawing pen for lines, fills, and text. */
454 static void SetBPen( struct RastPort *rp, unsigned long pen ) {
455 rp->BgPen = pen;
457 static unsigned GetAPen(struct RastPort *rp) {
458 return rp->FgPen;
460 static unsigned GetBPen(struct RastPort *rp) {
461 return rp->BgPen;
463 static unsigned GetPenColor(struct RastPort *rp, unsigned pen) {
464 assert(pen < sizeof(rp->custom.pencolors) / sizeof (rp->custom.pencolors[0]));
465 return rp->custom.pencolors[pen];
467 /* original uses ViewPort instead of RastPort */
468 static void SetRGB4( struct RastPort *vp, long index, unsigned long red, unsigned long green, unsigned long blue ) {
469 assert(index < sizeof(rp->custom.pencolors) / sizeof (rp->custom.pencolors[0]));
470 rp->custom.pencolors[index] = RGB(red*17, green*17, blue*17);
472 void RectFill( struct RastPort *rp, long xMin, long yMin, long xMax, long yMax ) {
473 ezsdl_fill_rect(SU(xMin), SU(yMin), xMax - xMin, yMax-yMin, GetPenColor(rp, GetAPen(rp)), SCALE);
476 // draw a line and move there
477 static void Draw( struct RastPort *rp, long x, long y ) {
478 //only implement straight lines
479 assert(x == rp->custom.x || y == rp->custom.y);
481 if(y != rp->custom.y)
482 ezsdl_draw_vline(SU(rp->custom.x), SU(MIN(y,rp->custom.y)), ABS(y-rp->custom.y), GetPenColor(rp, GetAPen(rp)), SCALE);
483 else
484 ezsdl_draw_hline(SU(MIN(x,rp->custom.x)), SU(rp->custom.y), ABS(x-rp->custom.x), GetPenColor(rp, GetAPen(rp)), SCALE);
486 assert(x<SCREENW);
487 assert(y<SCREENH);
489 rp->custom.x = x;
490 rp->custom.y = y;
491 ezsdl_refresh();
494 long Text( struct RastPort *rp, STRPTR string, unsigned long count ) {
495 char buf[80];
496 snprintf(buf, sizeof buf, "%*s", (int) count, string);
497 unsigned rl = get_font_render_length(buf);
498 assert(rp->custom.x+rl<=SCREENW);
499 if(rp->DrawMode == JAM2)
500 ezsdl_fill_rect(SU(rp->custom.x), SU(rp->custom.y), rl, FONT_H, GetPenColor(rp, GetBPen(rp)), SCALE);
501 struct spritesheet *font = GetPenColor(rp, GetAPen(rp)) == RGB(0,0,0) ? &ss_black_font : &ss_font;
502 draw_font(buf, font, rp->custom.x, rp->custom.y);
503 rp->custom.x+=rl;
504 ezsdl_refresh();
505 return 0;
508 /* clib/intuition_protos.h */
509 void DisplayBeep(void) {
510 /* makes the screen flash for an instant */
511 bmp4 *tmp = ezsdl_get_screenshot();
512 ezsdl_fill_rect(0, 0, SCREENW, SCREENH, RGB(255,255,255), SCALE);
513 ezsdl_refresh();
514 ezsdl_sleep(20);
515 ezsdl_draw(tmp, 0, 0, 1);
516 ezsdl_refresh();
517 free(tmp);
521 STUB(calc_taxes)
523 /* supposed to clear either the actual line or the line in which commands can be entered */
524 static void clear_line(void) {
525 ezsdl_fill_rect(0, SU(rp->custom.y), SCREENW, FONT_H, RGB(0,0,0), SCALE);
526 rp->custom.x = 0;
529 static void clear_top(void) {
530 ezsdl_fill_rect(0, 0, SCREENW, BOTTOM_START, RGB(0,0,0), SCALE);
531 ezsdl_refresh();
533 static void clear_bottom(void) {
534 ezsdl_fill_rect(0, SU(BOTTOM_START), SCREENW, SCREENH-BOTTOM_START, RGB(0,0,0), SCALE);
535 ezsdl_refresh();
538 STUB(earnings_display)
539 STUB(click)
541 static size_t word(char* s, int*end) {
542 size_t c = 0;
543 while(s[c] && !isspace(s[c])) c++;
544 *end = s[c] == 0;
545 s[c] = 0;
546 return c;
548 static char* skip_whitespace(char *s, int*end) {
549 while(*s && isspace(*s)) s++;
550 *end = !*s;
551 return s;
554 static int find_stock(char* sym) {
555 unsigned i;
556 for(i=0;i<ARRAY_SIZE(stock_array);i++)
557 if(!strcmp(sym, stock_array[i].name)) return i;
558 return -1;
561 static void TxWrite(struct RastPort *rp, const char *ch);
563 static void TxWritef(struct RastPort *rp, const char* fmt, ...) {
564 va_list ap;
565 va_start(ap, fmt);
566 char buf[100];
567 vsnprintf(buf, sizeof buf, fmt, ap);
568 va_end(ap);
569 TxWrite(rp, buf);
572 static int TxWriteNoMove(struct RastPort *rp, const char *s) {
573 int x = rp->custom.x;
574 TxWrite(rp, s);
575 rp->custom.x = x;
576 return FALSE;
579 static int TxWriteMsg(struct RastPort *rp, const char* fmt, ...) {
580 va_list ap;
581 va_start(ap, fmt);
582 char buf[100];
583 vsnprintf(buf, sizeof buf, fmt, ap);
584 va_end(ap);
585 message = TRUE;
586 return TxWriteNoMove(rp, buf);
589 static void cursorit(int y, int x, const char*fn, int line) {
590 #ifdef DEBUG_CALLS
591 dprintf(2, "%s called from %s:%d\n", __FUNCTION__, fn, line);
592 #endif
593 //Move(rp, x * 8, y * 8 + 6);
594 Move(rp, x*8, y*8);
597 static void display_rankings(void) {
598 static const int rankingstarty = 10;
599 int i;
600 clear_bottom();
601 cursor(8, 0);
602 clear_line();
603 cursor(rankingstarty, 0);
604 TxWrite(rp, " ""NET WORTH"" "" ");
605 cursor(rankingstarty+1,0);
606 TxWrite(rp, " ----------""----------""----------""--");
607 for(i=0;i<no_of_players;i++) {
608 cursor(rankingstarty+2+i, 4);
609 TxWrite(rp, players[i].name);
610 char buf[16];
611 int l = snprintf(buf, sizeof buf, "%.0f", players[i].net_worth);
612 cursor(rankingstarty+2+i, 40-4-l);
613 TxWrite(rp, buf);
615 cursor(rankingstarty+14,0);
618 //validity_check: supposed to check whether a user-entered command can be executed
619 // translates the command number
620 // prints "INVALID COMMAND WORD" if command is not known
621 // prints "YOU HAVEN'T GOT ENOUGH CASH" if not enough money
622 // returns TRUE or FALSE
623 // calls clear_line
624 static int validity_check(char *cmd, int *com_char_count,
625 int *com_no, int *units, int *stock_no,
626 int *trans_price, int *autobuy, int *autosell) {
627 // for weird reasons, the first char is always 0
628 cmd++;
629 clear_line();
630 if(!*com_char_count) return FALSE;
631 *com_char_count = 0;
632 unsigned i,l;
633 int end, si, numberonly = 0;
634 l = word(cmd, &end);
636 for(i=0;i<ARRAY_SIZE(commands);i++) if(!strcmp(cmd, commands[i])) goto found;
637 return TxWriteMsg(rp, "INVALID COMMAND WORD");
638 found:
639 *com_no = i;
640 if(!end) {
641 cmd+=l+1;
642 cmd=skip_whitespace(cmd, &end);
644 switch(*com_no) {
645 case GRAPH:
646 if(!q_break) goto end_qu;
647 if(end) goto incompl;
648 if((si = find_stock(cmd)) == -1) goto inv_stock;
649 *stock_no = si;
650 case SAVE:
651 case QUIT:
652 return TRUE;
653 case CASH:
654 case BONDS:
655 case JUMP: numberonly = 1;
656 case MARGIN:
657 case SELL:
658 case BUY:
659 if(end) goto incompl;
660 if(isdigit(*cmd)) {
661 l = word(cmd, &end);
662 if(end && !numberonly) goto missing_stock;
663 *units = atoi(cmd);
664 cmd += l+1;
665 cmd = skip_whitespace(cmd, &end);
666 if(end && !numberonly) goto missing_stock;
667 } else {
668 if(numberonly) goto incompl;
669 *units = 1;
671 if(!numberonly) {
672 if((si = find_stock(cmd)) == -1) goto inv_stock;
673 *stock_no = si;
674 *trans_price = stock_array[si].price * *units;
675 } else {
676 /* special case code for stuff where the dispatcher function doesnt validate */
677 switch(*com_no) {
678 case CASH: if(*units > cur_player->bonds) goto insuff_bonds; break;
681 return TRUE;
683 return TxWriteMsg(rp, "UNHANDLED COMMAND GIVEN");
684 incompl:
685 return TxWriteMsg(rp, "INCOMPLETE COMMAND GIVEN");
686 missing_stock:
687 return TxWriteMsg(rp, "NO STOCK NAME GIVEN");
688 inv_stock:
689 return TxWriteMsg(rp, "INVALID STOCK NAME GIVEN");
690 end_qu:
691 return TxWriteMsg(rp, "DATA AVAILABLE AT END OF QUARTER ONLY");
692 insuff_bonds:
693 return TxWriteMsg(rp, "INSUFFICIENT AMOUNT OF BONDS STOCKED");
696 STUB(change_player)
697 STUB(add_purchase)
698 STUB(del_purchase)
700 static double sqr(double x) {
701 return (x * x);
704 static void TxWrite(struct RastPort *rp, const char *ch) {
705 Text(rp, ch, strlen(ch));
709 /* expecting a scrollbuf of 41 chars */
710 static void scroll(char* scrollbuf, char u, int reset, int y, int bgpen) {
711 if(reset) memset(scrollbuf, ' ', sizeof scrollbuf-1);
712 scrollbuf[41-1] = 0;
713 memmove(scrollbuf, scrollbuf+1, 41-1);
714 scrollbuf[41-2] = u;
715 unsigned sx = rp->custom.x, sy = rp->custom.y;
716 SetAPen(rp, bgpen);
717 RectFill(rp, 0, y, 320, y+23);
718 Move(rp, 0, y+8);
719 SetBPen(rp, bgpen);
720 SetAPen(rp, 0);
721 TxWrite(rp, scrollbuf);
722 Move(rp, sx, sy);
723 SetAPen(rp, 1);
724 SetBPen(rp, 0);
727 /* scroll news */
728 static void scrollne(char u) {
729 static char scrollbuf[40+1];
730 scroll(scrollbuf, u, cur_news_line == -1, 32, 3);
733 static void scrollit(char u) {
734 static char scrollbuf[40+1];
735 static int initdone;
736 scroll(scrollbuf, u, !initdone, 32-24, 2);
737 initdone = 1;
740 static void load_tick_element(TICK_ITEM* t, int stockno) {
741 int l = snprintf(t->item, sizeof(t->item), "%s-%d ", stock_array[stockno].name, stock_array[stockno].price);
742 //memset(t->item+l, ' ', sizeof(t->item)-l);
743 //t->item[sizeof(t->item)-1]=0;
746 static long long timeval2utime(struct timeval *t) {
747 return (t->tv_sec * 1000LL * 1000LL) + t->tv_usec;
750 static long long getutime64(void) {
751 struct timeval t;
752 gettimeofday(&t, 0);
753 return timeval2utime(&t);
756 static int getmicros() {
757 // ULONG Seconds, Micros;
758 // CurrentTime(&Seconds,&Micros);
759 // return((int) (Micros % 100) + 1);
760 return getutime64() % 100 + 1;
764 static int gethundredths() {
765 // ULONG Seconds, Micros;
766 // CurrentTime(&Seconds,&Micros);
767 // return((int)Micros/10000);
768 return (getutime64()%1000000)/10000;
771 #if 0
772 float frand() {
773 return ((float) getmicros() / 101.0);
775 #else
776 float frand() {
777 return (float) rand() / RAND_MAX;
779 #endif
781 static float pi2 = 6.28;
782 static float myrandom(float stdev) {
783 float holder;
784 holder = (sqrt(-2.0 * log(frand())) * (cos(pi2 * frand()))) * stdev;
785 return (holder);
788 static float get_float(FILE * infile) {
789 char innum[20], c;
790 int i;
792 while(((c = getc(infile)) == ' ') || (c == '\015') || (c == '\012')) ;
793 innum[0] = c;
794 i = 1;
795 while(((c = getc(infile)) != ' ') && (c != '\015') && (c != '\012'))
796 innum[i++] = c;
797 innum[i] = '\0';
798 return ((float) atof(innum));
801 static int get_int(FILE * infile) {
802 char innum[10], c;
803 int i;
805 while(((c = getc(infile)) == ' ') || (c == '\015') || (c == '\012')) ;
806 innum[0] = c;
807 i = 1;
808 while(((c = getc(infile)) != ' ') && (c != '\015') && (c != '\012'))
809 innum[i++] = c;
810 innum[i] = '\0';
811 return (atoi(innum));
814 static float normal(float value) {
815 int i, flag;
816 float holder;
818 flag = FALSE;
819 value *= 10;
820 if(value < 0) {
821 value *= -1;
822 flag = TRUE;
824 i = (int) value;
825 if(i > 22)
826 holder = .999;
827 else
828 holder = ((value - ((float) i)) * ndis[i + 1]) - ((value - ((float) (i + 1))) * ndis[i]);
829 if(flag)
830 holder = 1.0 - holder;
832 DPRINTF("value is %f i is %d\n",value,i);
833 DPRINTF("normal returns %f\n",holder);
835 return (holder);
838 float variance(int stockno) {
839 float tvx1, tvx2, tvx3, tvx4;
840 tvx1 = vx1 + factor1;
841 tvx2 = vx2 + factor2;
842 tvx3 = vx3 + factor3;
843 tvx4 = vx4 + factor4;
844 DPRINTF("ran %f q_int %f\n",myrandom(2.0 * q_int_rate),q_int_rate);
845 DPRINTF("4 tvx1 %f tvx2 %f tvx3 %f tvx4 %f\n",tvx1,tvx2,tvx3,tvx4);
846 DPRINTF("st %d b1 %f sqr %f sq* %f\n",stockno,stock_array[stockno].b1,sqr(stock_array[stockno].b1),
847 (sqr(stock_array[stockno].b1) * tvx1));
848 DPRINTF("st %d b2 %f sqr %f sq* %f\n",stockno,stock_array[stockno].b2,sqr(stock_array[stockno].b2),
849 (sqr(stock_array[stockno].b2) * tvx2));
850 DPRINTF("st %d b3 %f sqr %f sq* %f\n",stockno,stock_array[stockno].b3,sqr(stock_array[stockno].b3),
851 (sqr(stock_array[stockno].b3) * tvx3));
852 DPRINTF("st %d e %f sqr %f sq* %f\n",stockno,stock_array[stockno].e,sqr(stock_array[stockno].e),
853 (sqr(stock_array[stockno].e) * tvx4));
855 return (((sqr(stock_array[stockno].b1) * tvx1) +
856 (sqr(stock_array[stockno].b2) * tvx2) +
857 (sqr(stock_array[stockno].b3) * tvx3) + (sqr(stock_array[stockno].e) * tvx4)) * 10.0);
860 static int kbhit() {
861 enum eventtypes e;
862 struct event myevent;
863 e = ezsdl_getevent(&myevent);
864 if(e != EV_KEYDOWN) return 0;
865 else return myevent.which;
868 static void end_year(void) {
869 int player, counter;
870 PLAYER *play_ptr;
872 clear_bottom();
873 scr_status = RANKINGSUP;
874 cursor(8, 13);
875 TxWrite(rp, "Taxes Assessed");
876 cursor(9, 13);
877 TxWrite(rp, "______________");
879 for(player = 0; player < no_of_players; ++player) {
880 play_ptr = &players[0] + player;
881 for(counter = 0; counter < play_ptr->auto_count; ++counter) {
882 if((play_ptr->auto_ptr[counter]->option_type == CALL) ||
883 (play_ptr->auto_ptr[counter]->option_type == PUT)) {
884 players[player].cash += (opt_value(player + 1, counter) * .985);
885 players[player].other_earnings += ((opt_value(player + 1, counter) * .985) -
886 players[player].auto_ptr[counter]->pur_price);
887 del_auto(counter, player + 1);
888 --counter;
890 } /* end for counter */
893 play_ptr->taxes += calc_taxes(player);
895 cursor(11 + player, 0);
896 TxWritef(rp, "%20s $%-10.0f", play_ptr->name, play_ptr->taxes);
897 if(play_ptr->taxes < 0) {
898 cursor(11 + player, 37);
899 TxWrite(rp, "CR");
900 } else if(play_ptr->taxes <= play_ptr->cash) {
901 play_ptr->cash -= play_ptr->taxes;
902 play_ptr->taxes = 0;
903 } else {
904 play_ptr->taxes -= play_ptr->cash;
905 play_ptr->cash = 0;
907 play_ptr->short_term = play_ptr->long_term = play_ptr->other_earnings = 0;
908 } /* end for players */
910 ++year;
911 week = 1;
912 upd_year();
913 year_over = TRUE;
914 clear_line();
915 TxWriteMsg(rp, "END OF YEAR"); // changed from TxWrite
918 static void execute(int com_no, int units, int stock_no, int price, int auto_minus, int auto_plus, int player) {
919 AUTOS *ptr;
920 int counter;
922 switch (com_no) {
923 case BUY:
924 if(price == NOT_FOUND) {
925 if(players[player - 1].auto_count < AUTOLIMIT) {
926 add_auto_exec(auto_minus, auto_plus, AUTOBUY, NONE, units, stock_no, player,
927 NOT_FOUND);
928 } else {
929 TxWriteMsg(rp, "YOU ALREADY HAVE %d AUTO TRANSACTIONS", AUTOLIMIT);
932 } else if(round(((float) units) * ((float) price) * 101.5) <= players[player - 1].cash) {
933 if((players[player - 1].portfolio[stock_no].shares != 0) ||
934 (players[player - 1].stock_count < STOCKLIMIT)) {
935 /* add a record node for tax purposes */
937 add_purchase(player, stock_no, units, price);
939 /* if its a new stock, note that his portfolio has grown */
941 if(players[player - 1].portfolio[stock_no].shares == 0)
942 ++players[player - 1].stock_count;
944 /* charge the player */
946 players[player - 1].cash -= round(((float) units) * ((float) price) * 101.5);
948 /* give him the stock */
950 players[player - 1].portfolio[stock_no].shares += units;
952 upd_coh();
953 upd_stock(stock_no);
955 } else { /* reached limit of holdings */
956 TxWriteMsg(rp, "YOU ALREADY HAVE %d STOCKS", STOCKLIMIT);
959 /* end if enough cash */
960 else { /* too little cash */
961 TxWriteMsg(rp, "YOU HAVEN'T GOT ENOUGH CASH");
964 break;
966 case SELL:
967 if(price == NOT_FOUND) {
968 if(players[player - 1].auto_count < AUTOLIMIT) {
969 add_auto_exec(auto_minus, auto_plus, AUTOSELL, NONE, units, stock_no, player, NOT_FOUND);
970 } else {
971 TxWriteMsg(rp, "YOU ALREADY HAVE %d AUTO TRANSACTIONS", AUTOLIMIT);
973 } else if((players[player - 1].portfolio[stock_no].shares >= units) && (units > 0)) {
975 /* pay the player for the stock he sold, first deducting */
976 /* any margin debt owed on those shares. */
978 if(round((double) players[player - 1].portfolio[stock_no].margin_debt) >=
979 round(((float) units) * ((float) stock_array[stock_no].price * 98.5)))
980 players[player - 1].portfolio[stock_no].margin_debt -=
981 round(98.5 * ((float) units) * ((float) stock_array[stock_no].price));
982 else {
983 players[player - 1].cash +=
984 round(((float) units) * ((float) stock_array[stock_no].price) * 98.5) -
985 round((double) players[player - 1].portfolio[stock_no].margin_debt);
986 players[player - 1].portfolio[stock_no].margin_debt = 0;
989 if(round((double) players[player - 1].portfolio[stock_no].margin_debt) < 1)
990 players[player - 1].portfolio[stock_no].margin_debt = 0;
992 /* remove or update the tax record node */
994 del_purchase(player, stock_no, units);
996 /* remove the shares from his portfolio */
998 players[player - 1].portfolio[stock_no].shares -= units;
1000 /* if he sold all his shares note his fewer holdings */
1002 if((players[player - 1].portfolio[stock_no].shares == 0) &&
1003 (players[player - 1].portfolio[stock_no].margin_debt == 0)) {
1004 players[player - 1].portfolio[stock_no].limit = 0;
1005 --players[player - 1].stock_count;
1008 upd_coh();
1009 upd_stock(stock_no);
1010 } else { /* if he doesn't have that many shares */
1011 if(players[player - 1].portfolio[stock_no].shares == 0)
1012 TxWriteMsg(rp, "YOU DON'T OWN ANY!");
1013 else
1014 TxWriteMsg(rp, "YOU DON'T HAVE THAT MANY SHARES");
1016 break;
1017 case CALL:
1018 if(round(((float) price) * ((float) units) * 1.015) <= players[player - 1].cash) {
1019 if(players[player - 1].auto_count < AUTOLIMIT) {
1020 add_auto_exec(NONE, NONE, CALL, stock_array[stock_no].price, units, stock_no,
1021 player, price);
1022 players[player - 1].cash -= round(((float) price) * ((float) units) * 1.015);
1023 upd_coh();
1024 upd_netw();
1026 } else {
1027 TxWriteMsg(rp, "YOU ALREADY HAVE %d AUTO TRANSACTIONS", AUTOLIMIT);
1029 } else { /* if he hasn't got the money */
1030 TxWriteMsg(rp, "YOU NEED SOME MORE CASH");
1032 break;
1033 case PUT:
1034 if(round(((float) price) * ((float) units) * 1.015) <= players[player - 1].cash) {
1035 if(players[player - 1].auto_count < AUTOLIMIT) {
1036 add_auto_exec(NONE, NONE, PUT, stock_array[stock_no].price, units, stock_no,
1037 player, price);
1038 players[player - 1].cash -= round(((float) price) * ((float) units) * 1.015);
1039 upd_coh();
1040 upd_netw();
1042 } else {
1043 TxWriteMsg(rp, "YOU ALREADY HAVE %d AUTO TRANSACTIONS", AUTOLIMIT);
1045 } else { /* if he hasn't got the money */
1046 TxWriteMsg(rp, "YOU NEED SOME MORE CASH");
1048 break;
1050 case MARGIN:
1051 if(round((((float) units) * ((float) price) * 103.0) / 2.0) <= players[player - 1].cash) {
1052 if((players[player - 1].portfolio[stock_no].shares != 0) ||
1053 (players[player - 1].stock_count < STOCKLIMIT)) {
1055 /* update or add a tax record node */
1057 add_purchase(player, stock_no, units, price);
1059 /* if its a new stock, note that his portfolio has grown */
1061 if(players[player - 1].portfolio[stock_no].shares == 0)
1062 ++players[player - 1].stock_count;
1064 /* charge the player half the cost */
1066 players[player - 1].cash -=
1067 round((((float) units) * ((float) price) * 103.0) / 2.0);
1069 /* put the other half on margin */
1071 players[player - 1].portfolio[stock_no].margin_debt +=
1072 round((100.0 * ((float) units) * ((float) price)) / 2.0);
1074 /* give him the stock */
1076 players[player - 1].portfolio[stock_no].shares += ((int) units);
1078 upd_coh();
1079 upd_stock(stock_no);
1081 } else { /* reached limit of holdings */
1082 TxWriteMsg(rp, "YOU ALREADY HAVE %d STOCKS", STOCKLIMIT);
1086 /* end if enough cash */
1087 else { /* too little cash */
1088 TxWriteMsg(rp, "YOU HAVEN'T GOT ENOUGH CASH");
1091 break;
1093 case DELETE:
1094 del_auto(units - 1, player);
1095 break;
1097 case QUIT:
1098 quit();
1099 break;
1101 case BONDS:
1102 bonds(units);
1103 break;
1105 case SAVE:
1106 save();
1107 break;
1109 case CASH:
1110 cur_player->cash += ((float) units) * 1000.0;
1111 cur_player->bonds -= units;
1112 upd_coh();
1113 upd_bonds();
1114 break;
1115 case GRAPH:
1116 graph(stock_no, year);
1117 if(newsline[cur_news_line] != '\n')
1118 cur_news_line = 0;
1119 break;
1121 case EXERCISE:
1122 ptr = cur_player->auto_ptr[units - 1];
1123 if((ptr->option_type == CALL) || (ptr->option_type == PUT)) {
1124 price = (int) round(.985 * ((float) price));
1125 cur_player->cash += (((float) price) * ((float) ptr->units));
1126 cur_player->other_earnings += ((((float) price) - ((float) ptr->pur_price)) *
1127 ((float) ptr->units));
1128 del_auto(units - 1, player);
1129 upd_coh();
1130 } else {
1131 TxWriteMsg(rp, "You Can't Exercise a Limit Order");
1133 break;
1135 case LIMIT:
1136 cur_player->portfolio[stock_no].limit = units;
1137 for(counter = 0; counter < screen_count; ++counter)
1138 if((scr_status == STOCKSUP) && (scr_ptr[counter]->stock_no == stock_no)) {
1139 cursor(12 + counter, 36);
1140 if(units != 0) {
1141 TxWritef(rp, "%3d", units);
1142 } else {
1143 TxWrite(rp, " ");
1146 break;
1148 case JUMP:
1149 jump_weeks = units;
1150 break;
1153 calc_netw(player);
1154 if((scr_status == STOCKSUP) || (scr_status == AUTOSUP))
1155 upd_netw();
1158 static void shutdown() {
1159 Delay(300);
1160 clear_line();
1161 TxWrite(rp, "Hit any key to continue");
1162 while(kbhit() == 0) ezsdl_sleep(20);
1163 exit(TRUE);
1166 static void quit(void) {
1167 int tplayer;
1168 int counter;
1169 PLAYER *play_ptr;
1171 for(tplayer = 0; tplayer < no_of_players; ++tplayer) {
1172 play_ptr = &players[0] + tplayer;
1173 for(counter = 0; counter < NO_OF_STOCKS; ++counter) {
1174 if(play_ptr->portfolio[counter].shares > 0)
1175 execute(SELL, play_ptr->portfolio[counter].shares, counter, stock_array[counter].price,
1176 NONE, NONE, tplayer + 1);
1178 for(counter = 0; counter < play_ptr->auto_count; ++counter) {
1179 if((play_ptr->auto_ptr[counter]->option_type == CALL) ||
1180 (play_ptr->auto_ptr[counter]->option_type == PUT)) {
1181 play_ptr->cash += opt_value(tplayer + 1, counter);
1182 del_auto(counter, tplayer + 1);
1186 display_rankings();
1187 clear_line();
1188 TxWrite(rp, "All Holdings Liquidated");
1189 TxWrite(rp, " That's It!");
1190 shutdown();
1193 static void set_graph() {
1194 int i;
1195 /* Set up graph initialization */
1196 SetAPen(rp, 5);
1197 Move(rp, 280, 176);
1198 Draw(rp, 116, 176);
1199 Draw(rp, 116, 16);
1200 SetAPen(rp, 1);
1201 for(i = 0; i < 5; ++i) {
1202 Move(rp, 124 + (i * 32), 176);
1203 Draw(rp, 124 + (i * 32), 183);
1205 SetAPen(rp, 0);
1206 SetBPen(rp, 5);
1207 cursor(5, 4);
1208 Text(rp, "X", 1);
1209 cursor(6, 4);
1210 Text(rp, "X", 1);
1211 cursor(7, 4);
1212 Text(rp, "X", 1);
1213 SetAPen(rp, 1);
1214 SetBPen(rp, 0);
1215 cursor(2, 10);
1216 TxWrite(rp, "200-");
1217 cursor(7, 10);
1218 TxWrite(rp, "150-");
1219 cursor(12, 10);
1220 TxWrite(rp, "100-");
1221 cursor(17, 11);
1222 TxWrite(rp, "50-");
1223 cursor(21, 11);
1224 TxWrite(rp, "10-");
1230 /***************************************************/
1231 /* Draws a line up from the bottom of the graph */
1232 /* starting at horizontal position, POSITION, and */
1233 /* continuing NUMBER of times in the COLOR. */
1234 /* */
1235 /* line_draw(position,number,color) */
1236 /* int position; */
1237 /* int number; */
1238 /* int color; */
1239 /***************************************************/
1242 static void line_draw(int position, int number, int color) {
1243 if((number > 0) && (number <= 200)) {
1244 SetAPen(rp, color);
1245 RectFill(rp, 112 + (position * 8), 175 - number, 119 + (position * 8), 175);
1246 SetAPen(rp, 1);
1252 #asm
1253 public reset_it
1254 reset_it proc near
1255 push bp
1256 mov bp,sp
1257 mov bx,4[bp]
1258 mov ax,6[bp]
1259 lbp11: cmp ax,9
1260 jl lbp12
1261 sub ax,8
1262 inc bx
1263 jmp lbp11
1264 lbp12: dec ax
1265 mov cx,ax
1266 mov dl, byte ptr [bx]
1267 cmp cl,1
1268 jl lbp13
1269 ror dl,cl
1270 lbp13: and dl,feh
1271 cmp cl,1
1272 jl lbp14
1273 mov cx,ax
1274 rol dl,cl
1275 lbp14: mov byte ptr [bx],dl
1276 pop bp
1278 reset_it endp
1279 #endasm
1283 #define RED 2
1284 #define GREEN 4
1285 #define BLUE 5
1287 static void graph(int stockno, int year) {
1288 int x;
1289 int color, tcolor;
1291 clear_top();
1292 clear_bottom();
1293 set_graph();
1294 year -= 4;
1295 color = RED;
1296 tcolor = NOT_FOUND;
1298 for(x = 0; x < 20; ++x) {
1300 if(history[stockno].splits[x]) {
1301 tcolor = color;
1302 color = BLUE;
1305 line_draw(x + 1, (int) round((((float) history[stockno].price[x]) * 0.8) + .49), color);
1306 SetDrMd(rp, JAM1);
1307 if(history[MMMS].price[x] != 0) {
1308 cursor((int)
1309 (round((((double) 21.51) - (((double) history[MMMS].price[x])) / ((double) 10.0)))),
1310 15 + x);
1311 TxWrite(rp, "*");
1313 SetDrMd(rp, JAM2);
1314 if(tcolor != NOT_FOUND) {
1315 if(color == RED)
1316 color = GREEN;
1317 else
1318 color = RED;
1319 tcolor = NOT_FOUND;
1321 if(color == RED)
1322 color = GREEN;
1323 else
1324 color = RED;
1325 if((x % 4) == 0) {
1326 cursor(23, 15 + x);
1327 if(year > 1900)
1328 TxWritef(rp, "%2d", year - 1900);
1329 else
1330 TxWritef(rp, "%2d", year);
1331 ++year;
1334 cursor(2, 32);
1335 TxWrite(rp, stock_array[stockno].name);
1336 cursor(1, 1);
1337 TxWrite(rp, "Stock");
1338 cursor(3, 1);
1339 TxWrite(rp, "Splits");
1340 scr_status = GRAPHUP;
1343 #define OPTIONS 1
1344 #define TAXES 2
1346 static void margin() {
1347 int player;
1348 int counter;
1349 static char owes[15];
1350 int found, passby;
1351 float dif, y;
1352 PLAYER *ptr;
1354 make_call = FALSE;
1355 owes[0] = 0;
1356 found = FALSE;
1357 passby = FALSE;
1359 for(player = 0; player < no_of_players; ++player) {
1360 ptr = &players[0] + player;
1362 for(counter = 0; counter < NO_OF_STOCKS; ++counter) {
1363 if((round((double) ptr->portfolio[counter].margin_debt) >
1364 (dif = (round((((float) ptr->portfolio[counter].shares) * 100.0 *
1365 ((float) stock_array[counter].price)) / 2.0))))) {
1366 dif = round((double) ptr->portfolio[counter].margin_debt) - dif;
1367 if(ptr->cash >= dif) {
1368 ptr->cash -= dif;
1369 ptr->portfolio[counter].margin_debt -= dif;
1370 passby = TRUE;
1371 } else {
1372 ptr->portfolio[counter].margin_debt -= ptr->cash;
1373 ptr->cash = 0;
1374 timer1.status = OFF;
1375 stop = TRUE;
1376 make_call = TRUE;
1377 owes[player] = 1;
1378 found = OPTIONS;
1380 if(round((double) ptr->portfolio[counter].margin_debt) < 1.0) {
1381 ptr->portfolio[counter].margin_debt = 0;
1382 if(ptr->portfolio[counter].shares == 0)
1383 --ptr->stock_count;
1385 if(cur_player == ptr) {
1386 upd_stock(counter);
1387 upd_coh();
1392 if(ptr->taxes > 0)
1393 if(ptr->cash < ptr->taxes) {
1395 ptr->taxes -= ptr->cash;
1396 ptr->cash = 0;
1397 found = TAXES;
1398 stop = TRUE;
1399 make_call = TRUE;
1400 owes[player + 4] = 1;
1401 } else {
1402 ptr->cash -= ptr->taxes;
1403 ptr->taxes = 0;
1406 if(cur_player == ptr) {
1407 calc_netw(player + 1);
1408 upd_netw();
1409 upd_coh();
1413 if(found || passby) {
1414 clear_line();
1415 message = TRUE; // can probably be removed
1416 if(passby && !found) {
1417 TxWriteMsg(rp, "MARGIN CALL ISSUED");
1418 } else if(stop) {
1419 int x = 0;
1420 if(found == OPTIONS) {
1421 clear_bottom();
1422 scr_status = RANKINGSUP;
1423 for(player = 0; player < no_of_players; ++player) {
1424 if(owes[player]) {
1425 cursor(11 + x, 4);
1426 ++x;
1427 TxWriteMsg(rp, "Player %d Must Settle Margin Debts", player + 1);
1430 } else {
1431 clear_bottom();
1432 scr_status = RANKINGSUP;
1433 for(player = 0; player < no_of_players; ++player) {
1434 if(owes[4 + player]) {
1435 cursor(11 + x, 5);
1436 ++x;
1437 TxWriteMsg(rp, "Player %d Must Settle Tax Debts", player + 1);
1442 for(player = 0; player < no_of_players; ++player) {
1443 ptr = &players[0] + player;
1444 /* FIXME: the original calc_netw function was missing a return statement, so this assignment is probably a bug */
1445 y = calc_netw(player + 1);
1446 if(!q_break)
1447 y -= (((float) ptr->bonds) * 1000.0);
1448 for(x = 0; x < players[player].auto_count; ++x) {
1449 if((players[player].auto_ptr[x]->option_type == CALL) ||
1450 (players[player].auto_ptr[x]->option_type == PUT))
1451 y += 1;
1454 if(y <= 0) {
1455 ptr->cash = 0;
1456 ptr->bonds = 0;
1457 ptr->net_worth = 0;
1458 ptr->auto_count = 0;
1459 ptr->stock_count = 0;
1460 ptr->taxes = 0;
1461 for(x = 0; x < NO_OF_STOCKS; ++x) {
1462 ptr->portfolio[x].shares = 0;
1463 ptr->portfolio[x].margin_debt = 0;
1465 display_rankings();
1466 clear_line();
1467 TxWriteMsg(rp, "%s IS BANKRUPT", ptr->name);
1469 } /* end going through players */
1473 if(stop == FALSE) {
1474 q_break = FALSE;
1475 year_over = FALSE;
1479 static void shift_it(char *str) {
1480 int i;
1481 for(i = 0; i < 16; ++i)
1482 str[i] = str[i + 4];
1485 static void end_quarter() {
1486 int player, x, y;
1487 float earnings;
1489 timer1.status = OFF;
1490 timer2.status = OFF;
1491 timer3.status = OFF;
1492 in_progress = FALSE;
1494 for(player = 0; player < no_of_players; ++player) {
1495 earnings = round((double) ((((float) players[player].bonds) * BONDVALUE) * bond_rate));
1496 players[player].cash += earnings;
1497 players[player].other_earnings += earnings;
1498 players[player].net_worth +=
1499 round((double) ((((float) players[player].bonds) * BONDVALUE) * bond_rate));
1501 for(x = 0; x < NO_OF_STOCKS; ++x)
1502 history[x].price[15 + quarter] = ((int) stock_array[x].price);
1503 if(quarter == 4)
1504 for(x = 0; x < NO_OF_STOCKS; ++x) {
1505 for(y = 0; y < 16; ++y)
1506 history[x].price[y] = history[x].price[y + 4];
1507 for(y = 16; y < 20; ++y)
1508 history[x].price[y] = 0;
1509 shift_it(history[x].splits);
1511 bond_rate = (q_int_rate * .85);
1512 upd_coh();
1513 upd_netw();
1514 q_break = TRUE;
1515 stop = TRUE;
1516 ++quarter;
1517 if(quarter == 5)
1518 quarter = 1;
1519 upd_quarter();
1520 clear_line();
1521 TxWriteMsg(rp, "END OF QUARTER");
1522 factor1 = sqr(0.2 * q_int_rate);
1523 factor2 = sqr(0.02 * q_int_rate);
1524 factor3 = sqr(0.04 * q_int_rate);
1525 factor4 = sqr(0.3 * q_int_rate);
1528 static void getsave() {
1529 FILE *saved;
1530 AUTOS *aptr;
1531 int stock, shares, price;
1532 int num, junk, tyear, player, counter, tweek;
1534 saved = fopen("save", "r");
1535 if(saved == NULL) {
1536 cursor(24, 0);
1537 TxWrite(rp, "NO SAVED GAME FOUND");
1538 exit(1);
1539 } else {
1540 clear_top();
1541 clear_bottom();
1542 no_of_players = get_int(saved);
1543 year = get_int(saved);
1544 quarter = (int) get_int(saved);
1545 week = (int) get_int(saved);
1546 if(year < 10)
1547 emphasis = (char) get_int(saved);
1548 prime_rate = get_float(saved);
1549 q_int_rate = get_float(saved);
1550 wk_int_rate = get_float(saved);
1551 bond_rate = get_float(saved);
1553 vx1 = get_float(saved);
1554 vx2 = get_float(saved);
1555 vx3 = get_float(saved);
1556 vx4 = get_float(saved);
1558 for(player = 0; player < no_of_players; ++player) {
1559 players[player].name_length = (int) get_int(saved);
1560 fgets(players[player].name, 21, saved);
1561 players[player].name[players[player].name_length] = '\0';
1562 players[player].cash = get_float(saved);
1563 players[player].net_worth = get_float(saved);
1564 players[player].taxes = get_float(saved);
1565 players[player].short_term = get_float(saved);
1566 players[player].long_term = get_float(saved);
1567 players[player].other_earnings = get_float(saved);
1568 players[player].bonds = (int) get_int(saved);
1569 players[player].stock_count = (int) get_int(saved);
1570 players[player].auto_count = (int) get_int(saved);
1572 for(counter = 0; counter < players[player].stock_count; ++counter) {
1573 stock = (int) get_int(saved);
1575 players[player].portfolio[stock].shares = (int) get_int(saved);
1576 players[player].portfolio[stock].margin_debt = get_float(saved);
1577 num = get_int(saved);
1578 tyear = year;
1579 tweek = week;
1580 for(junk = 0; junk < num; ++junk) {
1581 year = get_int(saved);
1582 week = (int) get_int(saved);
1583 shares = (int) get_int(saved);
1584 price = (int) get_int(saved);
1585 add_purchase(player + 1, stock, shares, price);
1587 year = tyear;
1588 week = tweek;
1590 for(counter = 0; counter < players[player].auto_count; ++counter) {
1591 aptr = players[player].auto_ptr[counter];
1592 aptr->minus_price = (int) get_int(saved);
1593 aptr->plus_price = (int) get_int(saved);
1594 aptr->option_type = (int) get_int(saved);
1595 aptr->option_price = (int) get_int(saved);
1596 aptr->units = (int) get_int(saved);
1597 aptr->stock_no = (int) get_int(saved);
1598 aptr->cur_price = (int) get_int(saved);
1599 aptr->pur_price = get_int(saved);
1602 for(counter = 0; counter < NO_OF_STOCKS; ++counter) {
1603 stock_array[counter].price = (int) get_int(saved);
1604 for(junk = 0; junk < 20; ++junk)
1605 history[counter].price[junk] = (int) get_int(saved);
1606 for(junk = 0; junk < 20; ++junk)
1607 history[counter].splits[junk] = (int) get_int(saved);
1609 fclose(saved);
1610 //unlink("save");
1611 load_screen();
1612 screen_upd();
1613 load_tick_element(&ticker[0], 0);
1614 load_tick_element(&ticker[0] + 1, 1);
1615 load_tick_element(&ticker[0] + 2, 2);
1619 static void headers2() {
1620 char inmoney[5];
1621 int money;
1622 int junk1_counter, junk2_counter, junk3_counter;
1623 char c;
1624 char *fgets();
1627 clear_top();
1628 clear_bottom();
1629 cursor(10, 6);
1630 TxWrite(rp, "How Many Will Be Playing?");
1632 c = kbhit();
1633 no_of_players = c;
1634 if(isdigit(no_of_players))
1635 no_of_players -= DIFFERENCE;
1636 else
1637 no_of_players = -1;
1639 if((no_of_players <= 0) || (no_of_players > 4))
1640 goto re;
1641 for(junk1_counter = 0; junk1_counter < no_of_players; ++junk1_counter) {
1642 clear_top();
1643 clear_bottom();
1644 cursor(10, 9);
1645 TxWritef(rp, "Enter Player %d's Name", junk1_counter + 1);
1646 cursor(12, 6);
1647 TxWrite(rp, "(Maximum Of 20 Characters)");
1648 cursor(14, 6);
1649 TxWrite(rp, "> ");
1650 junk3_counter = -1;
1651 while(junk3_counter < 20) {
1652 char c;
1654 c = (char) kbhit();
1655 if(c == 0)
1656 goto re2;
1657 if(isupper(c) || islower(c) || (c == ' ') || (c == '.') || (c == ',')) {
1658 ++junk3_counter;
1659 if(junk3_counter == 20) {
1660 DisplayBeep();
1661 --junk3_counter;
1662 } else {
1663 players[junk1_counter].name[junk3_counter] = c;
1664 TxWritef(rp, "%c", c);
1666 } else if(c == (char) CR) {
1667 players[junk1_counter].name[++junk3_counter] = '\0';
1668 junk3_counter = 20;
1669 } else if(c == BACKSP) {
1670 if(junk3_counter >= 0) {
1671 --junk3_counter;
1672 cursor(14, 9 + junk3_counter);
1673 Text(rp, " ", 1);
1674 cursor(14, 9 + junk3_counter);
1676 } else if(c != 0) {
1677 DisplayBeep();
1679 re2:
1680 c = c;
1682 junk2_counter = 0;
1683 while(players[junk1_counter].name[junk2_counter] != '\0')
1684 ++junk2_counter;
1685 if(junk2_counter > 20) {
1686 junk2_counter = 20;
1687 players[junk1_counter].name[19] = '\0';
1689 players[junk1_counter].name_length = junk2_counter;
1692 money = 0;
1693 while((money != 25) && (money != 100) && (money != 50)) {
1694 junk2_counter = 0;
1695 clear_top();
1696 clear_bottom();
1697 cursor(10, 5);
1698 TxWrite(rp, "How Much Money Would You Like?");
1699 cursor(11, 13);
1700 TxWrite(rp, "(In Thousands)");
1701 cursor(13, 10);
1702 TxWrite(rp, "Enter 25, 50, or 100");
1703 cursor(15, 18);
1704 TxWrite(rp, "> ");
1705 c = ' ';
1706 while(c != CR) {
1707 c = kbhit();
1708 if((isdigit(c)) && (junk2_counter < 3)) {
1709 inmoney[junk2_counter++] = c;
1710 inmoney[junk2_counter] = '\0';
1711 TxWritef(rp, "%c", c);
1712 } else if((c == BACKSP) && (junk2_counter != 0)) {
1713 inmoney[junk2_counter--] = '\0';
1714 cursor(15, 20 + junk2_counter);
1715 Text(rp, " ", 1);
1716 cursor(15, 20 + junk2_counter);
1717 } else if(c == CR)
1718 money = atoi(inmoney);
1722 for(junk1_counter = 0; junk1_counter < no_of_players; ++junk1_counter) {
1723 players[junk1_counter].cash = money * 1000.0;
1724 players[junk1_counter].net_worth = players[junk1_counter].cash;
1725 players[junk1_counter].stock_count = 0;
1727 clear_top();
1728 clear_bottom();
1731 static void getyear(int year) {
1732 FILE *in;
1733 int i, x, counter, found;
1734 char datfile[11];
1736 x = 1000;
1737 counter = 0;
1738 found = FALSE;
1739 while(x > 0) {
1740 i = year / x;
1741 if(i > 0)
1742 found = TRUE;
1743 year -= (i * x);
1744 x /= 10;
1745 if(found)
1746 datfile[counter++] = i + DIFFERENCE;
1748 datfile[counter++] = '.';
1749 datfile[counter++] = 'd';
1750 datfile[counter++] = 'a';
1751 datfile[counter++] = 't';
1752 datfile[counter++] = '\0';
1755 in = fopen(datfile, "r");
1756 y_mssg_count = 0;
1757 i = 0;
1759 high_prime = get_float(in);
1760 low_prime = get_float(in);
1761 x = get_int(in);
1763 if(quarter > 2) {
1764 for(i = 0; i < (2 * x); ++i) {
1765 while(getc(in) != '\n') ;
1767 x = get_int(in);
1769 y_mssg_count = x;
1771 for(i = 0; i < x; ++i) {
1772 fgets(yrly_mssgs.item[i].string, 82, in);
1773 yrly_mssgs.item[i].intr = get_float(in);
1774 yrly_mssgs.item[i].gnp = get_float(in);
1775 yrly_mssgs.item[i].pol = get_float(in);
1776 yrly_mssgs.item[i].var = get_float(in);
1778 yrly_mssgs.item[i].used = FALSE;
1779 DPRINTF("i is %d\n",i);
1780 DPRINTF("message %s \n",yrly_mssgs.item[i].string);
1783 if(quarter == 1) {
1784 vx1 = vx2 = vx3 = vx4 = 0;
1785 for(i = 0; i < y_mssg_count; ++i) {
1786 vx1 += sqr(yrly_mssgs.item[i].intr);
1787 vx2 += sqr(yrly_mssgs.item[i].gnp);
1788 vx3 += sqr(yrly_mssgs.item[i].pol);
1789 vx4 += sqr(yrly_mssgs.item[i].var - 1.0);
1791 x = get_int(in);
1792 for(i = 0; i < x; ++i) {
1794 while(getc(in) != '\n') ;
1795 vx1 += sqr(get_float(in));
1796 vx2 += sqr(get_float(in));
1797 vx3 += sqr(get_float(in));
1798 vx4 += sqr(get_float(in) - 1.0);
1800 x += y_mssg_count;
1802 vx1 /= (NO_STD_MESSAGES + x);
1803 vx2 /= (NO_STD_MESSAGES + x);
1804 vx3 /= (NO_STD_MESSAGES + x);
1805 vx4 /= (NO_STD_MESSAGES + x);
1808 fclose(in);
1809 DPRINTF("final messcount is %d\n",y_mssg_count);
1814 /***************************************************/
1815 /************ begin main body of event() *********/
1816 /***************************************************/
1817 static float x4, E, R;
1818 static float gamma1 = 1.2;
1819 static float gamma2 = .24;
1820 static float gamma3 = .24;
1822 static void event(int stockno, float news) {
1823 int i, x, y;
1824 int newshares;
1825 NODE *temp;
1826 if(stockno != MMMS) {
1830 x4 = ((((float) gethundredths()) - 50.0) / 5000.0) * news * stock_array[stockno].e;
1833 /* calculated expected rate of return using method 2 as outlined */
1836 E = ((gamma1 * stock_array[stockno].b1) +
1837 (gamma2 * stock_array[stockno].b2) + (gamma3 * stock_array[stockno].b3)) * the_interest;
1842 /* generate percent change in stock price */
1845 R = (((stock_array[stockno].b1 * x1) +
1846 (stock_array[stockno].b2 * x2) +
1847 (stock_array[stockno].b3 * x3) + (stock_array[stockno].e * x4) + E) * 1.15) + 1.0;
1851 /* check value of R to prevent negative stock prices */
1853 if(R < .01)
1854 R = .01;
1857 /* calculate new stock price */
1860 stock_array[stockno].price = (int) round((stock_array[stockno].price * R));
1862 if(stock_array[stockno].price >= SPLITPRICE) {
1863 history[stockno].splits[quarter + 15] = 1;
1864 stock_array[stockno].price /= 2;
1865 clear_line();
1866 TxWriteMsg(rp, "%s STOCK SPLITS 2 FOR 1", stock_array[stockno].name);
1867 cursor(24, 0);
1868 for(y = 0; y < no_of_players; ++y) {
1869 newshares = (int) players[y].portfolio[stockno].shares;
1871 if(((int) players[y].portfolio[stockno].shares) >= 5000) {
1872 players[y].portfolio[stockno].shares *= 2;
1873 players[y].cash += (((float) players[y].portfolio[stockno].shares) - 9999.0) *
1874 ((float) stock_array[stockno].price);
1875 players[y].other_earnings +=
1876 (((float) players[y].portfolio[stockno].shares) -
1877 9999.0) * ((float) stock_array[stockno].price);
1878 players[y].portfolio[stockno].shares = (int) 9999;
1879 } else
1880 players[y].portfolio[stockno].shares *= 2;
1882 newshares = players[y].portfolio[stockno].shares - newshares;
1884 if(((int) players[y].portfolio[MMMS].shares) > 0) {
1885 players[y].cash += ((float) players[y].portfolio[MMMS].shares) * 333.0;
1886 players[y].other_earnings +=
1887 ((float) players[y].portfolio[MMMS].shares) * 333.0;
1891 /*** adjust purchase record for splits *****/
1894 temp = players[y].portfolio[stockno].purchases;
1896 if(temp != NULL) {
1897 while(temp->next != NULL)
1898 temp = temp->next;
1901 while(temp != NULL) {
1902 if(((int) temp->shares) < newshares) {
1903 newshares -= (int) temp->shares;
1904 temp->shares *= 2;
1905 } else {
1906 temp->shares += (int) newshares;
1907 newshares = 0;
1909 temp->price /= 2;
1910 temp = temp->previous;
1916 /*** show splits on screen ***/
1918 upd_stock(stockno);
1921 } else {
1922 stock_array[MMMS].price = 0;
1923 x = 0;
1925 for(i = 0; i < NO_OF_STOCKS; ++i) {
1926 x += stock_array[i].price;
1929 x -= stock_array[GOLD].price;
1930 x -= stock_array[REALESTATE].price;
1931 stock_array[MMMS].price = x / (NO_OF_STOCKS - 3);
1934 } /* end procedure event() */
1937 static void stall(int x) {
1938 int staller;
1939 int flag, y, z;
1941 flag = FALSE;
1942 staller = y = gethundredths();
1943 if(x == LONG)
1944 staller += 10;
1945 else
1946 staller += 8;
1948 if(staller > 100) {
1949 staller -= 99;
1950 flag = TRUE;
1952 while(((z = gethundredths()) < staller) || (flag))
1953 if(z < y) {
1954 z = y;
1955 flag = FALSE;
1956 if(staller > 90)
1957 staller = 0;
1961 static void save() {
1962 int player, stock, temp, count;
1963 FILE *saveto;
1964 AUTOS *aptr;
1965 NODE *ptr;
1967 saveto = fopen("save", "w");
1968 if(saveto == NULL) {
1969 clear_line();
1970 TxWriteMsg(rp, "FAILED ATTEMPT TO SAVE");
1971 } else {
1972 fprintf(saveto, " %d %d %d %d ", no_of_players, year, quarter, week);
1973 if(year < 10)
1974 fprintf(saveto, " %d ", (int) emphasis);
1975 fprintf(saveto, "%6.4f %6.4f %6.4f %6.4f\n", prime_rate, q_int_rate, wk_int_rate, bond_rate);
1976 fprintf(saveto, "%8.6f %8.6f %8.6f %8.6f\n", vx1, vx2, vx3, vx4);
1977 for(player = 0; player < no_of_players; ++player) {
1978 fprintf(saveto, " %d %-20s\n", players[player].name_length, players[player].name);
1979 fprintf(saveto, "%f %f %f\n", players[player].cash, players[player].net_worth,
1980 players[player].taxes);
1981 fprintf(saveto, "%f %f %f\n", players[player].short_term, players[player].long_term,
1982 players[player].other_earnings);
1983 temp =
1984 fprintf(saveto, "%d %d %d\n", players[player].bonds, players[player].stock_count,
1985 players[player].auto_count);
1987 for(stock = 0; stock < NO_OF_STOCKS; ++stock) {
1988 if(players[player].portfolio[stock].shares > 0) {
1989 temp =
1990 fprintf(saveto, "%d %d %f\n", stock,
1991 players[player].portfolio[stock].shares,
1992 players[player].portfolio[stock].margin_debt);
1993 count = 1;
1994 ptr = players[player].portfolio[stock].purchases;
1995 while(ptr->next != NULL) {
1996 ++count;
1997 ptr = ptr->next;
1999 fprintf(saveto, "%d\n", count);
2000 ptr = players[player].portfolio[stock].purchases;
2001 while(ptr != NULL) {
2002 fprintf(saveto, "%d %d %d %d\n", ptr->year, ptr->week, ptr->shares,
2003 ptr->price);
2004 ptr = ptr->next;
2008 if(temp == -1)
2009 goto jump1;
2010 for(count = 0; count < players[player].auto_count; ++count) {
2011 aptr = players[player].auto_ptr[count];
2012 fprintf(saveto, " %d %d %d ", aptr->minus_price, aptr->plus_price, aptr->option_type);
2013 fprintf(saveto, "%d %d %d %d %d\n", aptr->option_price, aptr->units, aptr->stock_no,
2014 aptr->cur_price, aptr->pur_price);
2018 for(stock = 0; stock < NO_OF_STOCKS; ++stock) {
2019 fprintf(saveto, "%d\n", stock_array[stock].price);
2020 for(count = 0; count < 20; ++count)
2021 fprintf(saveto, "%d\n", history[stock].price[count]);
2022 for(count = 0; count < 20; ++count)
2023 fprintf(saveto, "%d\n", history[stock].splits[count]);
2025 temp = fclose(saveto);
2026 jump1:
2027 if(temp == -1) {
2028 clear_line();
2029 TxWriteMsg(rp, "FAILED ATTEMPT TO SAVE");
2030 } else {
2031 clear_line();
2032 TxWriteMsg(rp, "GAME OVER");
2033 shutdown();
2039 /********************************************/
2040 /*** begin main body of procedure OPTION ****/
2041 /********************************************/
2042 /* unused - maybe was called from one of the missing functions */
2043 static float option(int com_no, int stockno, int ex_price) {
2044 float d1, d2, vari, factor1, factor2, holder;
2045 float t;
2047 vari = variance(stockno);
2049 DPRINTF("stockno %d com_no %d\n",stockno,com_no);
2050 DPRINTF("variance is %f\n",vari);
2052 t = (53.0 - ((float) week)) / 13.0;
2053 DPRINTF("\n t is %d\nlog is %f\n",t,log10(1.0));
2055 factor1 = log10((float) stock_array[stockno].price / (float) ex_price);
2056 factor2 = (sqrt(vari) * sqrt((double) t));
2057 DPRINTF("factor 1 %f factor 2 %f\n",factor1,factor2);
2058 DPRINTF("sqrt vari %f sqrt t %f\n",sqrt(vari),sqrt((double) t));
2060 d1 = (factor1 + ((q_int_rate + (vari / 2.0)) * t)) / factor2;
2061 d2 = (factor1 + ((q_int_rate - (vari / 2.0)) * t)) / factor2;
2062 DPRINTF("d1 is %f d2 is %f\n",d1,d2);
2063 DPRINTF("vari / 2 * t %f\n",(vari/2.0) * t);
2065 if(com_no == CALL)
2066 holder =
2067 100.0 * ((stock_array[stockno].price * normal(d1)) -
2068 ((ex_price / exp((double) q_int_rate * t)) * normal(d2)));
2069 else
2070 holder =
2071 100.0 * (((ex_price / exp((double) q_int_rate * t)) * normal(-d2)) -
2072 (stock_array[stockno].price * normal(-d1)));
2074 DPRINTF("price calculated %f\n",holder);
2075 DPRINTF("stock %s price %d ow %f\n",stock_array[stockno].name,stock_array[stockno].price,exp(q_int_rate * t));
2077 if(holder < ((53.0 - ((float) week)) * 4.0))
2078 holder = (53.0 - ((float) week)) * 4.0;
2079 if((holder < ((stock_array[stockno].price - ex_price) * 100)) && (com_no == CALL))
2080 holder = ((stock_array[stockno].price - ex_price) * 100.0);
2081 if((holder < ((ex_price - stock_array[stockno].price) * 100)) && (com_no == PUT))
2082 holder = ((ex_price - stock_array[stockno].price) * 100.0);
2084 DPRINTF("price %f\n",holder);
2086 return (round(holder));
2090 static void bonds(int units) {
2091 if(units + ((int) players[player - 1].bonds) > 99) {
2092 clear_line();
2093 TxWriteMsg(rp, "Maximum of 99 bonds can be held");
2094 } else if((((float) units) * 1000.0) <= players[player - 1].cash) {
2095 players[player - 1].cash -= (((float) units) * 1000.0);
2096 upd_coh();
2097 players[player - 1].bonds += ((int) units);
2098 if(scr_status != RANKINGSUP)
2099 upd_bonds();
2100 } else {
2101 clear_line();
2102 TxWriteMsg(rp, "INSUFFICIENT FUNDS");
2106 static void init() {
2107 int i, x;
2109 /* initialize first quarter history */
2111 for(x = 0; x < NO_OF_STOCKS; ++x)
2112 history[x].price[15] = 100;
2114 /* link the ticker elements together */
2116 for(i = 0; i < TICK_SIZE; ++i) {
2117 cur_tick = &ticker[0] + 1;
2118 if(i != TICK_SIZE - 1)
2119 ticker[i].next = &ticker[0] + i + 1;
2120 else
2121 ticker[i].next = &ticker[0];
2122 if(i != 0)
2123 ticker[i].previous = &ticker[0] + i - 1;
2124 else
2125 ticker[i].previous = &ticker[0] + TICK_SIZE - 1;
2127 load_tick_element(&ticker[0] + i, i);
2129 } /* for loop setting up ticker */
2131 /* set up auto execute array and pointers */
2133 for(i = 0; i < MAXPLAYERS; ++i)
2134 for(x = 0; x < AUTOLIMIT; ++x)
2135 players[i].auto_ptr[x] = &players[i].auto_array[0] + x;
2137 /* set up screen array pointers */
2139 for(i = 0; i < STOCKLIMIT; ++i) {
2140 scr_ptr[i] = &screen[0] + i;
2144 /* initialize timers, timer1 in use, timer2 not in use */
2146 timer1.status = OFF;
2147 timer2.status = OFF;
2148 timer3.status = OFF;
2149 timer1.hour_changed = FALSE;
2150 timer2.hour_changed = FALSE;
2151 timer3.hour_changed = FALSE;
2153 cursor(24, 0);
2155 } /* procedure initialize */
2157 static void getstd(char *infile) {
2158 int i;
2159 FILE *in = fopen(infile, "r");
2160 for(i = 0; i < 30; ++i) {
2161 fgets(std_mssgs.item[i].string, 75, in);
2162 std_mssgs.item[i].intr = get_float(in);
2163 std_mssgs.item[i].gnp = get_float(in);
2164 std_mssgs.item[i].pol = get_float(in);
2165 std_mssgs.item[i].var = get_float(in);
2168 fclose(in);
2171 /* a procedure to write the credits etc. on the screen. It pauses */
2172 /* then clears the screen */
2174 static int headers1(void) {
2175 int stall;
2176 char file_name[8];
2177 int yorn, forh;
2178 int temp_year;
2179 char c;
2181 cursor(7, 7);
2182 TxWrite(rp, "The Financial Time Machine");
2183 cursor(9, 0);
2184 TxWrite(rp, "(C) 1985 by Lehner Communications, Inc.");
2185 cursor(14, 11);
2186 TxWrite(rp, "programmed by NMc");
2187 cursor(16, 6);
2188 TxWrite(rp, "special thanks to Ed Friedman");
2189 Delay(300);
2190 yorn = (int) ' ';
2191 while((yorn != (int) 'y') && (yorn != (int) 'Y') && (yorn != (int) 'n') && (yorn != (int) 'N')) {
2192 clear_top();
2193 clear_bottom();
2194 cursor(10, 7);
2195 TxWrite(rp, "Continue A Previous Game?");
2196 cursor(12, 13);
2197 TxWrite(rp, "(Type Y or N)");
2198 cursor(10, 33);
2199 re2:
2200 yorn = kbhit();
2201 if((yorn == (int) 'Y') || (yorn == (int) 'y')) {
2202 return (TRUE);
2203 } else if((yorn == (int) 'N') || (yorn == (int) 'n')) {
2204 temp_year = 0;
2205 forh = ' ';
2206 clear_top();
2207 clear_bottom();
2208 cursor(10, 0);
2209 TxWrite(rp, "Enter Historical Mode or Forecast Mode?");
2210 cursor(12, 13);
2211 TxWrite(rp, "(Type H or F)");
2212 while((forh != (int) 'F') && (forh != (int) 'f') && (forh != (int) 'H') && (forh != (int) 'h')) {
2213 cursor(24, 0);
2214 forh = kbhit();
2217 if((forh == (int) 'F') || (forh == (int) 'f')) {
2218 temp_year = 1;
2219 emphasis = '\0';
2220 clear_top();
2221 clear_bottom();
2222 cursor(6, 7);
2223 TxWrite(rp, "Forecast Mode Emphasis On:");
2224 cursor(10, 10);
2225 TxWrite(rp, "1) GNP Factors");
2226 cursor(12, 10);
2227 TxWrite(rp, "2) Political Factors");
2228 cursor(14, 10);
2229 TxWrite(rp, "3) Interest Rate Factors");
2230 cursor(18, 12);
2231 TxWrite(rp, "Type 1, 2, or 3");
2232 while((emphasis < '1') || (emphasis > '3')) {
2233 cursor(24, 0);
2234 emphasis = kbhit();
2237 switch (emphasis) {
2238 case '1':
2239 getstd("gnp.dat");
2240 break;
2241 case '2':
2242 getstd("pol.dat");
2243 break;
2244 default:
2245 getstd("int.dat");
2246 break;
2249 } else {
2250 getstd("std.dat");
2251 while((temp_year < 1930) || (temp_year > 1980)) {
2252 clear_top();
2253 clear_bottom();
2254 cursor(10, 10);
2255 TxWrite(rp, "Enter The Game Year ");
2256 cursor(12, 13);
2257 TxWrite(rp, "(1930 to 1980)");
2258 cursor(14, 17);
2259 TxWrite(rp, "> ");
2260 stall = 0;
2261 while(stall < 5) {
2262 c = kbhit();
2263 if((isdigit(c)) && (stall < 4)) {
2264 file_name[stall++] = c;
2265 TxWritef(rp, "%c", c);
2267 if((c == BACKSP) && (stall != 0)) {
2268 --stall;
2269 cursor(14, 18 + stall);
2270 Text(rp, " ", 1);
2271 cursor(14, 18 + stall);
2273 if((c == CR) && (stall == 4))
2274 stall = 5;
2276 temp_year = 0;
2277 file_name[5] = '\0';
2278 temp_year = atoi(file_name);
2281 } else
2282 goto re2;
2283 year = temp_year;
2284 clear_top();
2285 clear_bottom();
2288 return (FALSE);
2291 static void set_top_screen(void) {
2292 upd_quarter();
2294 cursor(0, 27);
2295 TxWrite(rp, "PRIME");
2296 upd_prime();
2298 upd_year();
2300 SetAPen(rp, 2);
2301 RectFill(rp, 0, 8, 320, 31);
2303 SetAPen(rp, 3);
2304 RectFill(rp, 0, 32, 320, 55);
2306 SetAPen(rp, 1);
2310 static void set1_bottom_screen() {
2311 cursor(8, 0);
2312 TxWrite(rp, "HOLDINGS");
2313 cursor(8, 34);
2314 TxWrite(rp, "PAGE 1");
2315 cursor(8, (39 - cur_player->name_length)/2);
2316 TxWrite(rp, cur_player->name);
2317 cursor(10, 1);
2318 TxWrite(rp, " S LOTS VALUE CP MARGIN LIMIT");
2319 cursor(22, 0);
2320 TxWrite(rp, "COH $");
2321 cursor(22, 17);
2322 TxWrite(rp, "NETW $");
2323 cursor(22, 36);
2324 TxWrite(rp, "T-");
2325 upd_bonds();
2326 upd_netw();
2327 upd_coh();
2329 SetAPen(rp, 5);
2330 /* Draw appropriate rectangles */
2331 Move(rp, 4, 92);
2332 Draw(rp, 4, 172);
2333 Draw(rp, 36, 172);
2334 Draw(rp, 36, 76);
2335 Draw(rp, 4, 76);
2336 Draw(rp, 4, 92);
2337 Draw(rp, 36, 92);
2338 Draw(rp, 36, 172);
2339 Draw(rp, 76, 172);
2340 Draw(rp, 76, 76);
2341 Draw(rp, 36, 76);
2342 Draw(rp, 36, 92);
2343 Draw(rp, 76, 92);
2344 Draw(rp, 76, 172);
2345 Draw(rp, 156, 172);
2346 Draw(rp, 156, 76);
2347 Draw(rp, 76, 76);
2348 Draw(rp, 76, 92);
2349 Draw(rp, 156, 92);
2350 Draw(rp, 156, 172);
2351 Draw(rp, 188, 172);
2352 Draw(rp, 188, 76);
2353 Draw(rp, 156, 76);
2354 Draw(rp, 156, 92);
2355 Draw(rp, 188, 92);
2356 Draw(rp, 188, 172);
2357 Draw(rp, 268, 172);
2358 Draw(rp, 268, 76);
2359 Draw(rp, 188, 76);
2360 Draw(rp, 188, 92);
2361 Draw(rp, 268, 92);
2362 Draw(rp, 268, 172);
2363 Draw(rp, 316, 172);
2364 Draw(rp, 316, 76);
2365 Draw(rp, 268, 76);
2366 Draw(rp, 268, 92);
2367 Draw(rp, 316, 92);
2368 SetAPen(rp, 1);
2370 cursor(23, 0);
2374 /* unused - maybe was called from one of the missing funcs */
2375 static void set2_bottom_screen() {
2376 int x;
2378 cursor(8, 0);
2379 TxWrite(rp, "HOLDINGS");
2380 cursor(8, 34);
2381 TxWrite(rp, "PAGE 2");
2382 cursor(8, (39 - cur_player->name_length)/2);
2383 TxWrite(rp, cur_player->name);
2384 cursor(10, 1);
2385 TxWrite(rp, " S LOTS VALUE OPTION CP BUY SELL");
2386 cursor(22, 0);
2387 TxWrite(rp, "COH $");
2388 cursor(22, 17);
2389 TxWrite(rp, "NETW $");
2390 cursor(22, 36);
2391 TxWrite(rp, "T-");
2392 upd_bonds();
2393 upd_netw();
2394 upd_coh();
2397 /************************************************************************/
2398 /********** begin assembler setup of screen characteristics *************/
2399 /************************************************************************/
2401 SetAPen(rp, 5);
2402 /* Draw appropriate rectangles */
2404 Move(rp, 4, 92);
2405 Draw(rp, 4, 172);
2406 Draw(rp, 36, 172);
2407 Draw(rp, 36, 76);
2408 Draw(rp, 4, 76);
2409 Draw(rp, 4, 92);
2410 Draw(rp, 36, 92);
2411 Draw(rp, 36, 172);
2412 Draw(rp, 76, 172);
2413 Draw(rp, 76, 76);
2414 Draw(rp, 36, 76);
2415 Draw(rp, 36, 92);
2416 Draw(rp, 76, 92);
2417 Draw(rp, 76, 172);
2418 Draw(rp, 156, 172);
2419 Draw(rp, 156, 76);
2420 Draw(rp, 76, 76);
2421 Draw(rp, 76, 92);
2422 Draw(rp, 156, 92);
2423 Draw(rp, 156, 172);
2424 Draw(rp, 212, 172);
2425 Draw(rp, 212, 76);
2426 Draw(rp, 156, 76);
2427 Draw(rp, 156, 92);
2428 Draw(rp, 212, 92);
2429 Draw(rp, 212, 172);
2430 Draw(rp, 244, 172);
2431 Draw(rp, 244, 76);
2432 Draw(rp, 212, 76);
2433 Draw(rp, 212, 92);
2434 Draw(rp, 244, 92);
2435 Draw(rp, 244, 172);
2436 Draw(rp, 276, 172);
2437 Draw(rp, 276, 76);
2438 Draw(rp, 244, 76);
2439 Draw(rp, 244, 92);
2440 Draw(rp, 276, 92);
2441 Draw(rp, 276, 172);
2442 Draw(rp, 316, 172);
2443 Draw(rp, 316, 76);
2444 Draw(rp, 276, 76);
2445 Draw(rp, 276, 92);
2446 Draw(rp, 316, 92);
2447 SetAPen(rp, 1);
2448 /************************************************************************/
2449 /*********** end assembler setup of screen characteristics **************/
2450 /************************************************************************/
2454 static void upd_com_line(int com_no, int units, int stock_no, int price, int autobuy, int autosell, char *com_array,
2455 int *com_char_count) {
2456 int divisor, variation;
2457 int counter, i, pr;
2458 int found_first; /* flag for finding non-zero int */
2461 i = 1;
2462 while((commands[com_no][i - 1] != '\0') && (commands[com_no][i - 1] != ' ')) {
2463 com_array[i] = commands[com_no][i - 1];
2464 ++i;
2466 if((com_no == QUIT) || (com_no == SAVE)) {
2467 --i;
2468 goto finish;
2469 } else {
2470 com_array[i] = ' ';
2473 /* put in the number of units, in characters */
2474 if(com_no != GRAPH) {
2475 divisor = 1000;
2476 found_first = FALSE;
2477 if(units == 0)
2478 com_array[++i] = '0';
2479 else {
2480 while(divisor >= 1) {
2481 if((!found_first) && ((units / divisor) >= 1))
2482 found_first = TRUE;
2483 if(found_first) {
2484 com_array[++i] = (int) (units / divisor) + DIFFERENCE;
2485 units = units - (((int) units / divisor) * divisor);
2487 divisor = divisor / 10;
2491 if((com_no == DELETE) || (com_no == BONDS) || (com_no == CASH) || (com_no == JUMP)) {
2492 if(com_no == JUMP) {
2493 com_array[++i] = ' ';
2494 com_array[++i] = 'W';
2495 com_array[++i] = 'E';
2496 com_array[++i] = 'E';
2497 com_array[++i] = 'K';
2498 com_array[++i] = 'S';
2500 *com_char_count = i;
2501 goto finish;
2502 } else {
2503 com_array[++i] = ' ';
2506 /* put in the stock name */
2508 if(com_no != EXERCISE) {
2509 for(counter = 0; stock_array[stock_no].name[counter] != '\0'; ++counter)
2510 com_array[++i] = stock_array[stock_no].name[counter];
2513 if((com_no == GRAPH) || (com_no == LIMIT))
2514 goto finish;
2516 /* put in the word AT */
2518 com_array[++i] = ' ';
2519 com_array[++i] = 'A';
2520 com_array[++i] = 'T';
2521 com_array[++i] = ' ';
2523 /* put in the price */
2525 variation = 1;
2527 nextcase:
2529 pr = NOT_FOUND;
2530 switch (variation) {
2531 case 1:
2532 if(price != NOT_FOUND) {
2533 pr = price;
2535 break;
2536 case 2:
2537 if(autobuy != NONE) {
2538 com_array[++i] = '-';
2539 pr = autobuy;
2541 break;
2542 case 3:
2543 if(autosell != NONE) {
2544 com_array[++i] = '+';
2545 pr = autosell;
2547 break;
2550 if(pr != NOT_FOUND) {
2551 divisor = 1000;
2552 found_first = FALSE;
2553 while(divisor >= 1) {
2554 if((!found_first) && ((pr / divisor) >= 1))
2555 found_first = TRUE;
2556 if(found_first) {
2557 com_array[++i] = (int) (pr / divisor) + DIFFERENCE;
2558 pr = pr - (((int) pr / divisor) * divisor);
2560 divisor = divisor / 10;
2563 com_array[++i] = ' ';
2566 ++variation;
2568 if(variation <= 3)
2569 goto nextcase;
2571 finish:
2573 *com_char_count = i;
2574 cursor(24, 0);
2575 for(counter = 1; counter <= i; counter++) {
2576 TxWritef(rp, "%c", com_array[counter]);
2578 } /* end procedure up_com_line() */
2581 static void add_auto_exec(int auto_minus, int auto_plus, int option, int opt_price, int units, int stockno, int player,
2582 int pur_price) {
2583 int count;
2585 count = players[player - 1].auto_count;
2587 players[player - 1].auto_ptr[count]->minus_price = auto_minus;
2588 players[player - 1].auto_ptr[count]->plus_price = auto_plus;
2589 players[player - 1].auto_ptr[count]->option_type = option;
2590 players[player - 1].auto_ptr[count]->option_price = opt_price;
2591 players[player - 1].auto_ptr[count]->units = units;
2592 players[player - 1].auto_ptr[count]->stock_no = stockno;
2593 players[player - 1].auto_ptr[count]->cur_price = stock_array[stockno].price;
2594 players[player - 1].auto_ptr[count]->pur_price = pur_price;
2596 ++players[player - 1].auto_count;
2598 if((cur_player == &players[0] + player - 1) && (scr_status == AUTOSUP))
2599 write_auto(count);
2600 cursor(24, 0);
2603 /************************************************************/
2604 /* Rewrites the entire set of auto execs for the cur_player */
2605 /************************************************************/
2607 static void auto_display() {
2608 int counter;
2610 for(counter = 0; counter < cur_player->auto_count; ++counter)
2611 write_auto(counter);
2612 cursor(24, 0);
2616 /************************************************************/
2617 /* Writes out a single auto exec of the current player */
2618 /************************************************************/
2620 static void write_auto(int position) {
2621 int stockno, cposition;
2623 stockno = cur_player->auto_ptr[position]->stock_no;
2624 cposition = position + 12;
2625 cursor(cposition, 1);
2626 TxWritef(rp, "%3s", stock_array[stockno].name);
2627 cursor(cposition, 5);
2628 TxWritef(rp, "%4d", cur_player->auto_ptr[position]->units);
2630 switch ((int) cur_player->auto_ptr[position]->option_type) {
2631 case PUT:
2632 cursor(cposition, 20);
2633 TxWrite(rp, "PU");
2634 cursor(cposition, 23);
2635 TxWritef(rp, "%3d", cur_player->auto_ptr[position]->option_price);
2636 cursor(cposition, 10);
2637 TxWritef(rp, "%9.0f", opt_value(player, position));
2638 break;
2639 case CALL:
2640 cursor(cposition, 20);
2641 TxWrite(rp, "CA");
2642 cursor(cposition, 23);
2643 TxWritef(rp, "%3d", cur_player->auto_ptr[position]->option_price);
2644 cursor(cposition, 10);
2645 TxWritef(rp, "%9.0f", opt_value(player, position));
2646 break;
2647 case AUTOSELL:
2648 case AUTOBUY:
2649 cursor(cposition, 10);
2650 TxWrite(rp, "LIMIT ORD");
2651 break;
2654 cursor(cposition, 27);
2655 TxWritef(rp, "%3d", cur_player->auto_ptr[position]->cur_price);
2657 cursor(cposition, 31);
2658 if(cur_player->auto_ptr[position]->option_type == AUTOBUY) {
2659 if(cur_player->auto_ptr[position]->minus_price != NONE) {
2660 TxWritef(rp, "%3d", cur_player->auto_ptr[position]->minus_price);
2661 } else if(cur_player->auto_ptr[position]->plus_price != NONE) {
2662 TxWritef(rp, "%3d", cur_player->auto_ptr[position]->plus_price);
2666 else {
2667 TxWritef(rp, "%3s", " - ");
2670 cursor(cposition, 36);
2671 if(cur_player->auto_ptr[position]->option_type == AUTOSELL) {
2672 if(cur_player->auto_ptr[position]->minus_price != NONE) {
2673 TxWritef(rp, "%3d", cur_player->auto_ptr[position]->minus_price);
2674 } else if(cur_player->auto_ptr[position]->plus_price != NONE) {
2675 TxWritef(rp, "%3d", cur_player->auto_ptr[position]->plus_price);
2677 } else {
2678 TxWritef(rp, "%3s", " - ");
2682 static void clear_auto(int position) {
2683 position += 12;
2684 cursor(position, 1);
2685 TxWrite(rp, " ");
2686 cursor(position, 5);
2687 TxWrite(rp, " ");
2688 cursor(position, 10);
2689 TxWrite(rp, " ");
2690 cursor(position, 20);
2691 TxWrite(rp, " ");
2692 cursor(position, 27);
2693 TxWrite(rp, " ");
2694 cursor(position, 31);
2695 TxWrite(rp, " ");
2696 cursor(position, 35);
2697 TxWrite(rp, " ");
2698 cursor(24, com_char_count);
2702 /************************************************************/
2703 /* Updates the current price of a stock in the cur_players */
2704 /* auto exec list and on the screen. */
2705 /************************************************************/
2707 static void upd_autos(int stockno) {
2708 int counter, flag;
2710 flag = FALSE;
2711 if(scr_status != RANKINGSUP) {
2712 for(counter = 0; counter < cur_player->auto_count; ++counter) {
2713 if((cur_player->auto_ptr[counter]->stock_no == stockno) &&
2714 (cur_player->auto_ptr[counter]->cur_price != stock_array[stockno].price)) {
2715 flag = TRUE;
2716 cur_player->auto_ptr[counter]->cur_price = stock_array[stockno].price;
2717 if(scr_status == AUTOSUP) {
2718 cursor(12 + counter, 27);
2719 TxWritef(rp, "%3d", stock_array[stockno].price);
2720 if((cur_player->auto_ptr[counter]->option_type != AUTOBUY) &&
2721 (cur_player->auto_ptr[counter]->option_type != AUTOSELL)) {
2722 cursor(12 + counter, 10);
2723 TxWritef(rp, "%9.0f", opt_value(player, counter));
2728 if(flag) {
2729 calc_netw(player);
2730 upd_netw();
2735 /** Calculates the value of the player's (1 - 4) option in auto ptr ****/
2736 /** POSITION. ****/
2738 static float opt_value(int player, int position) {
2739 PLAYER *ptr;
2740 float difference;
2741 int stock_price;
2743 ptr = &players[0] + player - 1;
2744 if(ptr == cur_player)
2745 stock_price = ptr->auto_ptr[position]->cur_price;
2746 else
2747 stock_price = stock_array[ptr->auto_ptr[position]->stock_no].price;
2749 DPRINTF("stock price is %d\n",stock_price);
2751 if(ptr->auto_ptr[position]->option_type == CALL)
2752 difference = (float) (((int) stock_price) - ((int) ptr->auto_ptr[position]->option_price));
2753 else
2754 difference = (float) (((int) ptr->auto_ptr[position]->option_price) - ((int) stock_price));
2756 DPRINTF("difference is %f\n",difference);
2758 difference *= (100.0 * ((float) ptr->auto_ptr[position]->units));
2759 DPRINTF("difference is now %f\n",difference);
2761 if(difference > 0)
2762 return (difference);
2763 else
2764 return (0);
2767 /****************************************************************************/
2768 /* This deletes the specified auto exec from the specified player. It */
2769 /* updates the screen if appropriate. */
2770 /****************************************************************************/
2772 static void del_auto(int position, int player) {
2773 int counter;
2774 AUTOS *tmp_ptr;
2776 tmp_ptr = players[player - 1].auto_ptr[position];
2777 for(counter = position; counter < AUTOLIMIT - 1; ++counter) {
2778 players[player - 1].auto_ptr[counter] = players[player - 1].auto_ptr[counter + 1];
2780 players[player - 1].auto_ptr[AUTOLIMIT - 1] = tmp_ptr;
2781 --players[player - 1].auto_count;
2782 if((cur_player == &players[0] + player - 1) && (scr_status == AUTOSUP)) {
2783 clear_auto(cur_player->auto_count);
2784 auto_display();
2789 static void chk_autos(int stockno) {
2790 int count, player, tunits;
2791 PLAYER *ptr;
2793 for(player = 1; player <= no_of_players; ++player) {
2794 ptr = &players[0] + player - 1;
2795 for(count = 0; count < ptr->auto_count; ++count) {
2796 tunits = (int) ptr->auto_ptr[count]->units;
2797 if((((int) ptr->auto_ptr[count]->stock_no) == stockno) &&
2798 (((int) ptr->auto_ptr[count]->option_type) == AUTOBUY)) {
2799 if((((int) ptr->auto_ptr[count]->minus_price) >= stock_array[stockno].price) &&
2800 (((int) ptr->auto_ptr[count]->minus_price) > 0) &&
2801 (ptr->cash >=
2802 round(((float) ptr->auto_ptr[count]->units) * ((float) stock_array[stockno].price) *
2803 101.5)) && (((int) ptr->stock_count) < STOCKLIMIT)) {
2804 del_auto(count, player);
2805 --count;
2806 execute(BUY, tunits, stockno, stock_array[stockno].price, NONE, NONE, player);
2807 } else if((((int) ptr->auto_ptr[count]->plus_price) <= stock_array[stockno].price) &&
2808 (((int) ptr->auto_ptr[count]->plus_price) > 0) &&
2809 (ptr->cash >= round(((float) ptr->auto_ptr[count]->units) *
2810 ((float) stock_array[stockno].price) * 101.5)) &&
2811 (((int) ptr->stock_count) < STOCKLIMIT))
2813 del_auto(count, player);
2814 --count;
2815 execute(BUY, tunits, stockno, stock_array[stockno].price, NONE, NONE, player);
2818 /* end if doing an auto_minus */
2819 else if((((int) ptr->auto_ptr[count]->stock_no) == stockno) &&
2820 (((int) ptr->auto_ptr[count]->option_type) == AUTOSELL)) {
2821 if((((int) ptr->auto_ptr[count]->minus_price) > 0) &&
2822 (((int) ptr->auto_ptr[count]->minus_price) >= stock_array[stockno].price)) {
2823 del_auto(count, player);
2824 --count;
2825 if(tunits > ((int) ptr->portfolio[stockno].shares))
2826 tunits = ((int) ptr->portfolio[stockno].shares);
2827 if(tunits > 0)
2828 execute(SELL, tunits, stockno, stock_array[stockno].price, NONE, NONE,
2829 player);
2830 } else if((((int) ptr->auto_ptr[count]->plus_price) > 0)
2831 && (((int) ptr->auto_ptr[count]->plus_price) <= stock_array[stockno].price)) {
2832 del_auto(count, player);
2833 --count;
2834 if(tunits > ((int) ptr->portfolio[stockno].shares))
2835 tunits = ((int) ptr->portfolio[stockno].shares);
2836 if(tunits > 0)
2837 execute(SELL, tunits, stockno, stock_array[stockno].price, NONE, NONE,
2838 player);
2842 /** end if doing an AUTOSELL **/
2844 for(count = 0; count < NO_OF_STOCKS; ++count) {
2845 if((((int) ptr->portfolio[count].limit) >= stock_array[count].price) &&
2846 (((int) ptr->portfolio[count].shares) > 0))
2847 execute(SELL, ((int) ptr->portfolio[count].shares), count, stock_array[stockno].price,
2848 NONE, NONE, player);
2854 static void upd_coh() {
2855 if((scr_status != RANKINGSUP) && (scr_status != GRAPHUP)) {
2856 cursor(22, 5);
2857 TxWritef(rp, "%-12.0f", cur_player->cash);
2858 cursor(24, 0);
2862 static void upd_netw() {
2863 if((scr_status != RANKINGSUP) && (scr_status != GRAPHUP)) {
2864 cursor(22, 23);
2865 TxWritef(rp, "%-12.0f", cur_player->net_worth);
2866 cursor(24, 0);
2870 static void upd_bonds() {
2871 if(scr_status != RANKINGSUP) {
2872 cursor(22, 38);
2873 TxWritef(rp, "%2d", cur_player->bonds);
2874 cursor(24, 0);
2878 static const char* getquartername(int q) {
2879 assert(q < 5 && q > 0);
2880 static const char quarters[4][4] = {"1ST", "2ND", "3RD", "4TH"};
2881 return quarters[q-1];
2884 static void upd_quarter() {
2885 int q = quarter % 4;
2886 if(!q) q = 4;
2887 cursor(0, 0);
2888 SetAPen(rp, 0);
2889 RectFill(rp, 0,0,FONT_W*3,FONT_H);
2890 SetAPen(rp, 1);
2891 TxWrite(rp,getquartername(q));
2892 TxWrite(rp, " QUARTER");
2893 cursor(24, com_char_count);
2896 static void upd_year() {
2897 if(year < 1000) {
2898 cursor(0, 17);
2899 TxWritef(rp, "YEAR %d", year);
2900 } else {
2901 cursor(0, 18);
2902 TxWritef(rp, "%4d", year);
2904 cursor(24, com_char_count);
2907 static void upd_prime() {
2908 float x;
2909 SetAPen(rp, 0);
2910 RectFill(rp,SCREENW-5*FONT_W,0,SCREENW,FONT_H);
2911 SetAPen(rp, 1);
2912 x = prime_rate * 100;
2913 cursor(0, 34);
2914 TxWritef(rp, "%5.2f%%", x);
2915 cursor(24, com_char_count);
2918 static void write_stock(int line_inc, int element) {
2919 int stockno;
2921 stockno = scr_ptr[element]->stock_no;
2922 cursor(12 + line_inc, 1);
2923 TxWritef(rp, "%3s", stock_array[stockno].name);
2924 cursor(12 + line_inc, 5);
2925 TxWritef(rp, "%4d", scr_ptr[element]->units);
2926 cursor(12 + line_inc, 10);
2927 TxWritef(rp, "%9.0f", ((float) cur_player->portfolio[stockno].shares) * (stock_array[stockno].price * 100.0));
2928 cursor(12 + line_inc, 20);
2929 TxWritef(rp, "%3d", scr_ptr[element]->price);
2930 cursor(12 + line_inc, 24);
2931 TxWritef(rp, "%9.0f", round((double) cur_player->portfolio[stockno].margin_debt));
2932 cursor(12 + line_inc, 36);
2933 if(cur_player->portfolio[stockno].limit > 0) {
2934 TxWritef(rp, "%3d", cur_player->portfolio[stockno].limit);
2935 } else {
2936 TxWritef(rp, "%3s", " ");
2940 static void clear_stock(int line_inc) {
2941 line_inc += 12;
2942 cursor(line_inc, 1);
2943 TxWritef(rp, "%3s", " ");
2944 cursor(line_inc, 5);
2945 TxWritef(rp, "%4s", " ");
2946 cursor(line_inc, 10);
2947 TxWritef(rp, "%9s", " ");
2948 cursor(line_inc, 20);
2949 TxWritef(rp, "%3s", " ");
2950 cursor(line_inc, 24);
2951 TxWritef(rp, "%9s", " ");
2952 cursor(line_inc, 34);
2953 TxWritef(rp, "%5s", " ");
2957 static void load_screen() {
2958 int counter;
2960 screen_count = 0;
2961 for(counter = 0; counter < NO_OF_STOCKS; ++counter) {
2962 if((cur_player->portfolio[counter].shares > 0) || (cur_player->portfolio[counter].margin_debt > 0)) {
2963 scr_ptr[screen_count]->stock_no = ((int) counter);
2964 scr_ptr[screen_count]->price = ((int) stock_array[counter].price);
2965 scr_ptr[screen_count]->margin_debt = cur_player->portfolio[counter].margin_debt;
2966 scr_ptr[screen_count]->units = cur_player->portfolio[counter].shares;
2967 ++screen_count;
2970 for(counter = 0; counter < cur_player->auto_count; ++counter) {
2971 cur_player->auto_ptr[counter]->cur_price =
2972 ((int) stock_array[cur_player->auto_ptr[counter]->stock_no].price);
2977 /* This procedure loops through all the current players holdings and auto */
2978 /* execs and updates the entire screen of data. */
2980 static void screen_upd(void) {
2981 int counter;
2982 for(counter = 0; counter < screen_count; ++counter) {
2983 write_stock(counter, counter);
2987 static double calc_netw(int player) {
2988 int counter, is_up;
2989 double total, difference;
2991 total = 0;
2992 if((cur_player == &players[0] + player - 1) && (scr_status == STOCKSUP))
2993 is_up = TRUE;
2994 else
2995 is_up = FALSE;
2996 if(is_up) {
2997 for(counter = 0; counter < cur_player->stock_count; ++counter) {
2998 total += (100.0 * ((float) scr_ptr[counter]->units) * ((float) scr_ptr[counter]->price))
2999 - round((double) scr_ptr[counter]->margin_debt);
3001 } else {
3002 for(counter = 0; counter < NO_OF_STOCKS; ++counter) {
3003 total += (100.0 * ((float) players[player - 1].portfolio[counter].shares) *
3004 ((float) stock_array[counter].price)) -
3005 players[player - 1].portfolio[counter].margin_debt;
3008 for(counter = 0; counter < players[player - 1].auto_count; ++counter) {
3009 if((players[player - 1].auto_ptr[counter]->option_type == PUT) ||
3010 (players[player - 1].auto_ptr[counter]->option_type == CALL))
3012 difference = opt_value(player, counter);
3014 else
3015 /* if it is an auto transaction instead of an option */
3016 difference = 0;
3018 total += difference;
3021 total += players[player - 1].cash;
3022 total += ((float) players[player - 1].bonds) * 1000.0;
3024 players[player - 1].net_worth = total;
3025 return total;
3028 static void upd_stock(int stockno) {
3029 int tally, counter;
3030 float garbage;
3032 tally = 0;
3033 counter = 0;
3035 if(scr_status == STOCKSUP) {
3036 while((scr_ptr[tally]->stock_no != stockno) && (tally < screen_count)) ++tally;
3038 /* if the stock is a new acquisition */
3040 if((tally == screen_count) && (cur_player->portfolio[stockno].shares != 0)) {
3041 scr_ptr[screen_count]->stock_no = stockno;
3042 scr_ptr[screen_count]->units = cur_player->portfolio[stockno].shares;
3043 scr_ptr[screen_count]->price = stock_array[stockno].price;
3044 scr_ptr[screen_count]->margin_debt = cur_player->portfolio[stockno].margin_debt;
3046 write_stock(tally, screen_count);
3047 ++screen_count;
3048 goto continue4;
3051 /* if player has sold all shares of the stock */
3053 if((cur_player->portfolio[stockno].shares == 0) &&
3054 (cur_player->portfolio[stockno].margin_debt == 0) && (tally < screen_count)) {
3055 SCREEN *tmp_ptr;
3057 tmp_ptr = scr_ptr[tally];
3058 for(counter = tally; counter < STOCKLIMIT - 1; ++counter) {
3059 scr_ptr[counter] = scr_ptr[counter + 1];
3061 scr_ptr[STOCKLIMIT - 1] = tmp_ptr;
3062 --screen_count;
3063 for(counter = tally; counter < screen_count; ++counter) {
3064 write_stock(counter, counter);
3066 clear_stock(screen_count);
3067 cursor(24, 0);
3068 goto continue4;
3071 /* if a change in the amount or value of a stock already held occured */
3073 if((cur_player->portfolio[stockno].shares > 0) || (cur_player->portfolio[stockno].margin_debt > 0)) {
3074 /* update the players netw according to the current prices */
3076 if(scr_ptr[tally]->price != stock_array[stockno].price) {
3077 cur_player->net_worth +=
3078 (float) (((int) stock_array[stockno].price -
3079 (int) scr_ptr[tally]->price) * 100.0 * ((int) scr_ptr[tally]->units));
3080 upd_netw();
3081 scr_ptr[tally]->price = stock_array[stockno].price;
3082 cursor(12 + tally, 10);
3083 garbage = (float) (scr_ptr[tally]->price) * (float) (scr_ptr[tally]->units) * 100.0;
3084 TxWritef(rp, "%9.0f", garbage);
3085 cursor(12 + tally, 20);
3086 TxWritef(rp, "%3d", scr_ptr[tally]->price);
3087 cursor(24, com_char_count);
3088 goto continue3;
3090 if(scr_ptr[tally]->units != cur_player->portfolio[stockno].shares) {
3091 scr_ptr[tally]->units = cur_player->portfolio[stockno].shares;
3092 scr_ptr[tally]->margin_debt = cur_player->portfolio[stockno].margin_debt;
3093 write_stock(tally, tally);
3094 cursor(24, com_char_count);
3095 goto continue3;
3097 if(scr_ptr[tally]->margin_debt != cur_player->portfolio[stockno].margin_debt) {
3098 scr_ptr[tally]->margin_debt = cur_player->portfolio[stockno].margin_debt;
3099 cursor(12 + tally, 24);
3100 TxWritef(rp, "%9.0f", round((float) scr_ptr[tally]->margin_debt));
3101 cursor(24, com_char_count);
3103 continue3:
3104 if((cur_player->portfolio[stockno].shares == 0) && (!stop))
3105 make_call = TRUE;
3107 /* end: update a current holding */
3108 continue4:;
3109 } /* end: if rankings aren't up */
3112 int main() {
3113 int stock, ic, i;
3114 char c;
3115 int junk_counter; /* a throwaway counter variable */
3116 int hit; /* which PLAYER function key was hit */
3118 cur_player = &players[0]; /* set current player as player 1 */
3120 ezsdl_init(SU(SCREENW), SU(SCREENH));
3121 init_gfx();
3122 struct RastPort foo = {0};
3123 rp = &foo;
3125 SetRGB4(rp,0,0,0,0);
3126 SetRGB4(rp,1,15,15,15);
3127 SetRGB4(rp,2,15,0,0);
3128 SetRGB4(rp,3,15,15,0);
3129 SetRGB4(rp,4,0,15,0);
3130 SetRGB4(rp,5,0,0,15);
3132 SetAPen(rp, 1);
3133 SetDrMd(rp, JAM2);
3135 /* puts us in 40x25 color text mode */
3139 /* build the ticker ring and set up the player data, initialize timers */
3141 init();
3143 for(junk_counter = 0; junk_counter < NO_OF_STOCKS; ++junk_counter) {
3144 players[0].portfolio[junk_counter].purchases = NULL;
3145 players[1].portfolio[junk_counter].purchases = NULL;
3146 players[2].portfolio[junk_counter].purchases = NULL;
3147 players[3].portfolio[junk_counter].purchases = NULL;
3150 /* header messages sent then screen cleared */
3151 i = headers1();
3152 if(i == TRUE) {
3153 getsave();
3154 if(year > 10) {
3155 getstd("std.dat");
3156 goto cont4;
3158 if(emphasis == '1') {
3159 getstd("gnp.dat");
3160 goto cont4;
3162 if(emphasis == '2') {
3163 getstd("pol.dat");
3164 goto cont4;
3167 getstd("int.dat");
3168 goto cont4;
3170 headers2();
3172 cont4:
3173 getyear(year); /** no overlay as of 11/22/85 **/
3175 prime_rate = (high_prime + low_prime) / 2.0;
3177 /* puts in the news and stock ticker lines, quarter, prime rate, etc. */
3179 set_top_screen();
3181 /* sets up the player data section, player name, coh, netw, etc. */
3183 set1_bottom_screen();
3186 while((year != 1985) && (year != 6)) {
3187 // reduce CPU usage
3188 ezsdl_sleep(1);
3190 if(((ic = kbhit()) != 0) || ((q_break == TRUE) && (jump_weeks > 0) && (make_call == FALSE))) {
3192 if(message) {
3193 clear_line();
3194 message = FALSE;
3195 com_char_count = 0;
3198 if((q_break == TRUE) && (jump_weeks > 0) && (make_call == FALSE)) {
3199 c = F10;
3200 } else {
3201 c = (char) ic;
3204 if(((scr_status == RANKINGSUP) || (scr_status == GRAPHUP)) && ((c < -80) || (c > -71))) {
3206 if(scr_status == GRAPHUP) {
3207 clear_top();
3208 set_top_screen();
3209 tick_position = 0;
3211 scr_status = STOCKSUP;
3212 clear_bottom();
3213 set1_bottom_screen();
3214 load_screen();
3215 screen_upd();
3216 upd_coh();
3217 calc_netw(player);
3218 upd_netw();
3219 upd_bonds();
3222 if((c >= -80) && (c <= -71)) {
3224 if(scr_status == GRAPHUP) {
3225 scr_status = RANKINGSUP;
3226 clear_top();
3227 set_top_screen();
3228 tick_position = 0;
3231 switch (c) {
3232 case -79:
3233 if(timer2.status == OFF)
3234 tmp_player = 1; /* F1 */
3235 hit = 1;
3236 break;
3237 case -78:
3238 if(timer2.status == OFF)
3239 tmp_player = 2; /* F1 */
3240 hit = 2;
3241 break;
3242 case -77:
3243 if(timer2.status == OFF)
3244 tmp_player = 3; /* F3 */
3245 hit = 3;
3246 break;
3247 case -76:
3248 if(timer2.status == OFF)
3249 tmp_player = 4; /* F4 */
3250 hit = 4;
3251 break;
3252 case -73:
3253 display_rankings();
3254 scr_status = RANKINGSUP; /* F7 */
3255 com_char_count = 0;
3256 hit = NOT_FOUND;
3257 break;
3258 case -72:
3259 earnings_display();
3260 scr_status = RANKINGSUP; /* F8 */
3261 com_char_count = 0;
3262 hit = NOT_FOUND;
3263 break;
3265 case -71:
3266 clear_bottom();
3267 cursor(10, 0);
3268 for(stock = 0; stock < (NO_OF_STOCKS - 1); stock += 3) {
3269 cursor(10 + (int) (stock / 3), 0);
3270 TxWritef(rp, " %3s - %3d %3s - %3d %3s - %3d",
3271 stock_array[alpha[stock]].name,
3272 stock_array[alpha[stock]].price,
3273 stock_array[alpha[stock + 1]].name,
3274 stock_array[alpha[stock + 1]].price,
3275 stock_array[alpha[stock + 2]].name,
3276 stock_array[alpha[stock + 2]].price);
3278 cursor(21, 15);
3279 #if 0
3280 tempstr[0] = stock_array[MMMS].name[0];
3281 tempstr[1] = stock_array[MMMS].name[1];
3282 tempstr[2] = stock_array[MMMS].name[2];
3283 tempstr[3] = stock_array[MMMS].name[3];
3284 #endif
3285 TxWritef(rp, "%3s - %3d", stock_array[MMMS].name, stock_array[MMMS].price);
3286 clear_line();
3287 scr_status = RANKINGSUP; /* F9 */
3288 com_char_count = 0;
3289 hit = NOT_FOUND;
3290 break;
3292 case -80:
3293 hit = NOT_FOUND;
3295 /* toggle: stop or restart game */
3297 if(timer1.status == OFF) {
3298 stop = FALSE;
3299 margin();
3300 /** no overlay as of 11/22/85 **/
3301 } else {
3302 stop = TRUE;
3304 break;
3305 default:
3306 DisplayBeep();
3307 hit = NOT_FOUND;
3308 break;
3311 if(((hit != NOT_FOUND) && (timer2.status == OFF)) || (hit == player)) {
3312 if(((com_char_count == 0) ||
3313 (player == hit) || (timer1.status == OFF)) && (hit == player)) {
3314 change_player(hit);
3315 goto continue1;
3317 if(((com_char_count == 0) ||
3318 (player == hit) || (timer1.status == OFF)) && (hit != player)) {
3319 timer2.status = OFF;
3320 change_player(tmp_player);
3321 goto continue1;
3324 timer2.status = ON;
3325 timer2.count = time_count + CHANGEOVERTIME;
3327 /* if the timer is about to run over the hour we set a flag and then set */
3328 /* the timer beyond the hour change */
3330 if(timer2.count >= 3599) {
3331 timer2.count -= 3599;
3332 timer2.hour_changed = TRUE;
3336 goto continue1;
3339 if(c == BACKSP) {
3340 if(com_char_count != 0) {
3341 --com_char_count;
3342 cursor(24, com_char_count);
3343 Text(rp, " ", 1);
3344 cursor(24, com_char_count);
3346 goto continue1;
3348 if(c == ESC) {
3349 if(validity_check
3350 (com_array, &com_char_count, &com_no, &units, &stock_no, &trans_price, &autobuy,
3351 &autosell) == TRUE) {
3352 clear_line();
3353 upd_com_line(com_no, units, stock_no, trans_price, autobuy, autosell, com_array,
3354 &com_char_count);
3357 goto continue1;
3359 if(c == CR) {
3360 com_array[1+com_char_count] = 0;
3361 if(com_char_count == 0) {
3362 timer2.count = 0;
3363 timer2.hour_changed = FALSE;
3365 if(validity_check
3366 (com_array, &com_char_count, &com_no, &units, &stock_no, &trans_price, &autobuy,
3367 &autosell) == TRUE) {
3368 com_char_count = 0;
3369 timer2.count = 0; /* timer over */
3370 timer2.hour_changed = FALSE;
3371 clear_line();
3372 execute(com_no, units, stock_no, trans_price, autobuy, autosell, player);
3373 cursor(24, 0);
3375 goto continue1;
3377 if(c == BREAK) {
3378 int x;
3379 cursor(24, 0);
3380 for(x = 1; x <= com_char_count; ++x) {
3381 TxWrite(rp, " ");
3383 cursor(24, 0);
3384 com_char_count = 0;
3385 goto continue1;
3387 if(c == CLICK_CHANGE) {
3388 if(click_on == TRUE)
3389 click_on = FALSE;
3390 else
3391 click_on = TRUE;
3393 goto continue1;
3395 if(com_char_count == 29) { /* buffer is full */
3396 DisplayBeep();
3397 goto continue1;
3399 if(isdigit(c)) {
3400 ++com_char_count;
3401 com_array[com_char_count] = c;
3402 TxWritef(rp, "%c", c);
3403 goto continue1;
3405 if((isupper(c)) || (c == ' ') || (c == '+') || (c == '-') || (c == '*')) {
3406 ++com_char_count;
3407 com_array[com_char_count] = c;
3408 TxWritef(rp, "%c", c);
3409 goto continue1;
3411 if(islower(c)) {
3412 c = toupper(c);
3413 ++com_char_count;
3414 com_array[com_char_count] = c;
3415 TxWritef(rp, "%c", c);
3416 goto continue1;
3418 DisplayBeep();
3423 /* end if kbhit() */
3424 /********** BEGIN SCREEN SCROLLING STUFF ****************/
3425 continue1:
3426 if(timer1.status == ON) {
3427 if(newsline[cur_news_line] == '\n')
3429 if((half_way == -2) && (in_progress == TRUE)) {
3430 half_way = load_stock + 6;
3431 if(half_way > (NO_OF_STOCKS - 1))
3432 half_way -= NO_OF_STOCKS;
3436 newsch = ' ';
3437 delay = !delay;
3440 } else {
3441 if(delay == TRUE) {
3443 delay = FALSE;
3444 if(cur_news_line == -1)
3445 newsch = ' ';
3446 else
3447 newsch = newsline[cur_news_line++];
3448 } else {
3449 delay = TRUE;
3454 if(cur_tick->item[tick_position] == '\0') {
3455 tick_position = 0;
3456 ++time_count;
3457 if(time_count == 3600)
3458 time_count = 0;
3459 cur_tick = cur_tick->next;
3460 if(in_progress == TRUE) {
3461 event(load_stock, var);
3462 if(half_way == load_stock) {
3463 half_way = -1;
3464 cur_news_line = 0;
3467 if(jump_weeks < 1)
3468 stall(SHORT);
3469 } else {
3470 if(jump_weeks < 1)
3471 stall(LONG);
3473 load_tick_element(cur_tick->previous, load_stock);
3474 chk_autos(load_stock);
3475 upd_stock(load_stock);
3476 upd_autos(load_stock);
3477 cursor(24, com_char_count);
3478 if(load_stock != NO_OF_STOCKS - 1)
3479 ++load_stock;
3480 else
3481 load_stock = 0;
3482 } else {
3483 if(jump_weeks < 1)
3484 stall(LONG);
3486 if(!delay)
3487 scrollne(newsch);
3488 scrollit(cur_tick->item[tick_position]);
3489 ++tick_position;
3490 if(click_on == TRUE)
3491 click();
3494 /************ END SCREEN SCROLLING STUFF ****************/
3498 time = time_count;
3499 if(time == 0) {
3500 timer1.hour_changed = FALSE;
3501 timer2.hour_changed = FALSE;
3502 timer3.hour_changed = FALSE;
3505 if((timer3.status == OFF) &&
3506 (!stop) && (!in_progress) && ((cur_news_line == -1) || (newsline[cur_news_line] == '\n'))) {
3507 timer3.count = time + 8 + ((int) round((double) frand() * 3.0));
3508 if(timer3.count >= 3599) {
3509 timer3.count -= 3599;
3510 timer3.hour_changed = TRUE;
3512 timer3.status = ON;
3514 } else if((timer3.status == ON) && (time > timer3.count) && (!in_progress) && (!timer3.hour_changed)) {
3515 float j, k, l, m;
3517 cur_news_line = 0;
3518 half_way = -2;
3519 j = frand();
3520 k = ((float) y_mssg_count - 0.00001);
3521 l = j * k;
3522 messno = (int) l;
3523 DPRINTF("%f %f %f %f %d %d\n",j,k,l,m,messno,y_mssg_count);
3525 if(yrly_mssgs.item[messno].used == FALSE) {
3527 for(g = 0; g < 82; ++g)
3528 newsline[g] = yrly_mssgs.item[messno].string[g];
3530 yrly_mssgs.item[messno].used = TRUE;
3531 mess_type = YRLY;
3533 } else {
3536 messno = (int) (frand() * 29.9999);
3539 for(g = 0; g < 82; ++g)
3540 newsline[g] = std_mssgs.item[messno].string[g];
3541 mess_type = STD;
3544 in_progress = 2;
3546 if(mess_type == STD) {
3547 gnp = std_mssgs.item[messno].gnp;
3548 pol = std_mssgs.item[messno].pol;
3549 intr = std_mssgs.item[messno].intr;
3550 var = std_mssgs.item[messno].var;
3552 } else {
3553 gnp = yrly_mssgs.item[messno].gnp;
3554 pol = yrly_mssgs.item[messno].pol;
3555 intr = yrly_mssgs.item[messno].intr;
3556 var = yrly_mssgs.item[messno].var;
3559 instd1 = .2 * q_int_rate;
3560 instd2 = .02 * q_int_rate;
3561 instd3 = .04 * q_int_rate;
3562 instd4 = .3 * q_int_rate;
3564 x1 = myrandom(instd1) + gnp;
3565 x2 = myrandom(instd2) + pol;
3566 x3 = myrandom(instd4) + intr;
3568 prime_rate -= intr / 2.0;
3569 if(prime_rate > high_prime)
3570 prime_rate = high_prime;
3571 else if(prime_rate < low_prime)
3572 prime_rate = low_prime;
3573 q_int_rate = pow(prime_rate + 1.0, 0.25) - 1.0;
3574 upd_prime();
3576 the_interest = ((float) weeks) * q_int_rate / 13.0;
3578 weeks = ((int) week) - ((int) event_week);
3579 if(weeks < 0)
3580 weeks = 52 - ((int) event_week) + ((int) week);
3581 event_week = (int) week;
3583 loop_to = load_stock + 2;
3584 if(loop_to > (NO_OF_STOCKS - 1))
3585 loop_to -= NO_OF_STOCKS;
3587 } else if((in_progress) && (load_stock == loop_to)) {
3588 --in_progress;
3589 if(in_progress == TRUE) {
3590 event(loop_to - 1, var);
3591 if(loop_to == 0)
3592 loop_to = NO_OF_STOCKS - 1;
3593 else
3594 --loop_to;
3596 } else
3597 event(MMMS, var);
3598 timer3.status = OFF;
3601 if(timer2.status == ON) {
3602 /* if time for changing players has run out then change 'em */
3604 if((time > timer2.count) && (!timer2.hour_changed)) {
3605 com_char_count = 0; /* delete stuff in progress */
3606 clear_line();
3607 change_player(tmp_player);
3608 timer2.status = OFF;
3612 /* see if it's time to start a new week */
3614 if(timer1.status == ON) {
3615 int x, y;
3617 if((time > timer1.count) && (!timer1.hour_changed)) {
3618 ++week;
3620 if(jump_weeks > 0)
3621 --jump_weeks;
3622 for(x = 0; x < no_of_players; ++x) {
3623 for(y = 0; y < NO_OF_STOCKS; ++y) {
3624 players[x].portfolio[y].margin_debt *= (1.0 + wk_int_rate);
3625 upd_stock(y);
3628 if(make_call == TRUE)
3629 margin();
3630 /** no overlay as of 11/22/85 **/
3631 wk_int_rate = (q_int_rate / 13.0) * 1.15;
3632 if(((int) week) % 13 == 1) {
3633 end_quarter();
3634 /** no overlay as of 11/22/85 **/
3635 margin();
3636 /** no overlay as of 11/22/85 **/
3637 if(((int) week) == 53)
3638 end_year();
3639 /** no overlay as of 11/22/85 **/
3640 if(((((int) quarter) == 3) || (((int) quarter) == 1))
3641 && ((year != 1985) && (year != 6)))
3642 getyear(year);
3643 /** no overlay as of 11/22/85 **/
3644 } else if(stop == TRUE) {
3645 timer1.status = OFF;
3646 timer2.status = OFF;
3647 timer3.status = OFF;
3648 } else {
3649 cursor(24, com_char_count);
3650 timer1.count = time_count + WEEKLENGTH;
3651 if(timer1.count >= 3599) {
3652 timer1.count -= 3599;
3653 timer1.hour_changed = TRUE;
3657 } else if((timer1.status == OFF) && (!q_break) && (!stop)) {
3658 timer1.status = ON;
3659 if((timer1.count = (time_count + WEEKLENGTH)) > 3599) {
3660 timer1.count -= 3599;
3661 timer1.hour_changed = TRUE;
3664 } /* while year != 1985 nor 6 */
3666 quit();
3667 return 0;