/* ** === WtSta.C -- Status line control for WT */ #include #include #include #include #include "wt.h" #include "wtcom.h" #include "wtkbd.h" #include "wtser.h" #include "wtwin.h" /* ===== Definition of status line ===== */ /* 1 2 3 4 5 6 7 8 */ /* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */ /* Name..... [102400] 100/100 -11 hits! RWT: 23:59:59 BLT: ..17.5 */ #define POS_NAME 2 #define POS_SCORE 13 #define POS_STAM 23 #define POS_MAXS 27 #define POS_HITS 31 #define POS_RWCH 54 #define POS_RWC 59 #define POS_BLCH 69 #define POS_BLC 74 #define MAX_NEW_P 40 #define iswiz(p) (p->level >= 10) /*=================*/ /*===== Types =====*/ /*=================*/ struct player { char name[NAME_STR]; int active; int level; int newp; int visible; long age; }; /*=====================*/ /*===== Variables =====*/ /*=====================*/ extern int level_colors[] = { /* Public! */ COLR_NULL, COLR_NOVI, COLR_WARR, COLR_HERO, COLR_CHAM, COLR_SUPE, COLR_ENCH, COLR_SORC, COLR_NECR, COLR_LEGE, COLR_WIZA, COLR_WIZA }; static long score; static int stam; static int maxs; static int hits; static int playing; static int repeating; static int repeat_tix; static int looping; static int loop_tix; static int sleeping; static int sleep_ticks; static long bl_time; static long bl_ticks; static struct player self; static struct player cur_players[MAX_PLAYERS]; static struct player const *end_cur = cur_players + MAX_PLAYERS; static struct player new_players[MAX_NEW_P]; static struct player *end_new; static int n_new_p = 0; static int in_users = 0; /*===========================*/ /*===== Local functions =====*/ /*===========================*/ void sta_blc(void); static void sta_stam3(void); /************************************************/ /* next_player(): return pointer to next player */ /* of given level in current_players[] */ /************************************************/ struct player *next_player(struct player *current, struct player *example) { int ic; if (current == NULL) { ic = -1; } else { ic = (word) (current - cur_players); } if (example->level >= 10) { /* wizard */ if (ic == -1) { return &cur_players[10]; } else if (ic == 0) { return NULL; } else if (ic == 19) { return &cur_players[9]; } else if (ic >= 10) { return &cur_players[ic+1]; } else { return &cur_players[ic-1]; } } else { /* mortal */ if (ic == -1) { return &cur_players[0]; } else if (ic == 10) { return NULL; } else if (ic == 9) { return &cur_players[19]; } else if (ic < 9) { return &cur_players[ic+1]; } else { return &cur_players[ic-1]; } } } /* end next_player() */ /*******************************/ /* sta_blc(): Display BL clock */ /*******************************/ void sta_blc(void) { char fmt_ticks[10]; long bl_mins, bl_secs; bl_ticks = bl_time / 6; bl_mins = bl_ticks / 10; bl_secs = bl_ticks % 10L; sprintf(fmt_ticks, "%4ld.%1ld", bl_mins, bl_secs); win_select(WIN_STAT); if (! playing) { win_fg(BLACK); } win_x(POS_BLC); win_puts(fmt_ticks); } /* end sta_blc() */ /************************************************/ /* sta_stam3(): Display combined stamina status */ /************************************************/ static void sta_stam3(void) { char fmt_stam[20]; win_select(WIN_STAT); /* --- stamina --- */ sprintf (fmt_stam, "%3d/", stam); if (stam < maxs || hits > 0) { win_blink(1); win_fg(WHITE); } win_x(POS_STAM); win_puts(fmt_stam); win_blink(0); win_fg(BLACK); /* --- maximum stamina --- */ sprintf (fmt_stam, "%3d", maxs); win_x(POS_MAXS); win_puts(fmt_stam); /* --- hits --- */ if (hits == 0) { sprintf(fmt_stam, "%-9s", " "); win_blink(0); } else { sprintf(fmt_stam, "-%2d hits!", hits); win_blink(1); win_fg(WHITE); } win_x(POS_HITS); win_puts(fmt_stam); win_blink(0); win_fg(BLACK); } /* end sta_stam3() */ /*************************************************/ /* sta_fkeys(): Display players on function keys */ /*************************************************/ void sta_fkeys(void) { int j; int krow; /* 1 = top row, 2 = bottom row */ int xpos; char tmp_name[10]; int fore_att, back_att; struct player *pcur; win_select(WIN_FKEY); krow = 1; for (j=1,pcur=cur_players,xpos=0; j<=MAX_PLAYERS; j++,pcur++,xpos+=8) { if (xpos >= DPY_COLS) { krow = 0; xpos = 0; } if (xpos == 0) { win_xy(0,krow); } win_att(MK_ATT(WHITE,BLACK)); if (pcur->active) { sprintf(tmp_name, "%1d", j%10); } else { strcpy(tmp_name, " "); } win_x(xpos); win_puts(tmp_name); if (pcur->active) { sprintf(tmp_name, "%-7.7s", pcur->name); fore_att = BLACK; if (!pcur->visible) { fore_att = YELLOW; } else if (iswiz(pcur)) { fore_att = LIGHTMAGENTA; } if (pcur->newp) win_blink(1); back_att = level_colors[pcur->level]; win_att(MK_ATT(fore_att, back_att)); win_x(xpos+1); win_puts(tmp_name); } } /* end for */ } /* end sta_fkeys() */ /****************************************************/ /* update_players(): Update the list on the F keys. */ /****************************************************/ static void update_players(void) { struct player *pcur, *pnew, *ptmp; int found; end_new = new_players + n_new_p; /* --- loop thru current players, check if in new players --- */ for (pcur=cur_players; pcuractive) { found = 0; for (pnew=new_players; pnewactive && !strcmp(pcur->name, pnew->name)) { pnew->active = 0; if (pcur->visible) { pcur->newp = 0; } else { pcur->visible = 1; pcur->newp = 1; } pcur->level = pnew->level; found = 1; break; } } if (! found) { if (pcur->visible) { pcur->visible = 0; pcur->newp = 1; pcur->age = bl_time; } else if (pcur->newp) { pcur->newp = 0; } else { if ((bl_time - pcur->age) > 120) { /* 2 minutes */ pcur->active = 0; } } } } } /* end for all current players */ /* ** --- Now CUR contains all previously known players, updated ** to reflect which ones are no longer new and which ones ** --- are newly invisible. */ /* ** --- Keep looping through all NEW entries; find the highest- ** level active entry and try to find a place for it in the ** --- CURRENT list. */ for (;;) { /* --- find highest level active NEW entry. --- */ pnew = NULL; for (ptmp=new_players; ptmpactive && (pnew==NULL || ptmp->level>pnew->level)) { pnew = ptmp; } } if (pnew==NULL) break; /* ** --- look for first inactive location in CURRENT, ** or the lowest ranking old invisible, ** --- or the lowest ranking old visible lower than NEW. */ ptmp = NULL; pcur = next_player(NULL, pnew); for (; pcur!=NULL; pcur=next_player(pcur, pnew)) { if (! pcur->active) { ptmp = pcur; break; } else if (pcur->newp) { continue; } else if (ptmp==NULL) { if (!pcur->visible || pcur->level < pnew->level) { ptmp = pcur; } } else if (ptmp->visible) { if (!pcur->visible || pcur->level < ptmp->level) { ptmp = pcur; } } else { /* ptmp invis */ if (!pcur->visible && pcur->level < ptmp->level) { ptmp = pcur; } } /* end if */ } /* end while */ if (ptmp == NULL) break; *ptmp = *pnew; pnew->active = 0; } /* end while */ /* --- clear new player list. --- */ n_new_p = 0; end_new = &new_players[0]; /* === list should now be up to date. redisplay. === */ sta_fkeys(); } /* end update_players() */ /*============================*/ /*===== Global functions =====*/ /*============================*/ /*********************************/ /* sta_init(): Initialize status */ /*********************************/ void sta_init(void) { playing = 0; sleeping = 0; bl_time = 0; repeating = 0; looping = 0; win_select(WIN_STAT); win_fg(BLACK); win_x(POS_RWCH); win_puts("RWT:"); self.name[0] = '\0'; memset(cur_players, 0, sizeof(cur_players)); memset(new_players, 0, sizeof(new_players)); sta_fkeys(); } /* end sta_init() */ /*****************************************/ /* sta_ownname(): Update own player name */ /*****************************************/ void sta_ownname(char *name) { char tmp_name[NAME_STR]; strcpy(self.name, name); sprintf(tmp_name, "%*s", NAME_LEN, name); win_select(WIN_STAT); win_x(POS_NAME); win_puts(tmp_name); } /* end sta_ownname() */ /*****************************/ /* sta_score(): Update score */ /*****************************/ void sta_score(char *raw_score) { long tmp_score; char fmt_score[9]; if (sscanf(raw_score, "%ld", &tmp_score)) { score = tmp_score; sprintf(fmt_score, "[%6ld]", score); win_select(WIN_STAT); win_x(POS_SCORE); win_puts(fmt_score); } } /* end sta_score() */ /******************************/ /* sta_stam(): Update stamina */ /******************************/ void sta_stam(char *raw_stam) { int tmp_stam; if (sscanf(raw_stam, "%d", &tmp_stam)) { stam = tmp_stam; hits = 0; sta_stam3(); } } /* end sta_stam() */ /***********************************/ /* sta_maxs(): Update max. stamina */ /***********************************/ void sta_maxs(char *raw_maxs) { int tmp_maxs; if (sscanf(raw_maxs, "%d", &tmp_maxs)) { maxs = tmp_maxs; sta_stam3(); } } /* end sta_maxs() */ /*****************************************/ /* sta_hits(): Update hits since last QS */ /*****************************************/ void sta_hit(void) { hits++; sta_stam3(); } /* end sta_hit() */ /***********************************************/ /* sta_keytran(): get contents of function key */ /***********************************************/ char *sta_keytran(int key_no) { struct player *pcur; pcur = &cur_players[key_no-1]; if (pcur->active) { return pcur->name; } else { return ""; } } /* end sta_keytran() */ /*************************************************/ /* sta_loop(): start or stop keyboard repetition */ /* (like sta_repeat(), but faster! */ /*************************************************/ void sta_loop(int mode) { if (mode) { looping = 1; loop_tix = 0; } else { looping = 0; } } /* end sta_loop() */ /***************************************/ /* sta_sleep(): Turn sleep mode on/off */ /***************************************/ void sta_sleep(int mode) { sleeping = mode; sleep_ticks = 0; } /* end sta_sleep() */ /*************************************/ /* sta_play(): Turn play mode on/off */ /*************************************/ void sta_play(int mode) { struct player *pcur; playing = mode; win_select(WIN_STAT); if (playing) { win_fg(BLACK); win_x(POS_BLCH); win_puts("BLT:"); } else { for (pcur=cur_players; pcuractive) pcur->visible = 0; } sta_fkeys(); } sta_blc(); } /* end sta_play() */ /**************************************************/ /* sta_player(): register player from QU ur USERS */ /* mode = 0: normal QU / WHO */ /* mode = 1: "has entered" */ /**************************************************/ void sta_player(char *player, int level, int mode) { char copy[80]; /* bigger as of 02/98 */ char *pcopy; struct player *newp, *pcur, *pnew; /* --- if line begins with '|', it was snooped. --- */ /* but we only trust our own QU, so trash it. */ if (player[0] == '|') return; /* --- remove leading garbage from player name. Must start w UC --- */ while (*player && ! isupper(*player)) { player++; } if (! *player) return; /* --- remove trailing garbage (only alpha significant) --- */ for (pcopy=copy; isalpha(*player); player++) { *pcopy++ = *player; } *pcopy = '\0'; if (*player != '\0' && *player != ' ' && *player != ')') return; if (! copy[0]) return; if (strlen(copy) > NAME_LEN) return; /* new as of 02/98 */ if (mode == 0) { in_users = 2; } if (! strcmp(copy, self.name)) return; if (mode == 1) { n_new_p = 0; end_new = &new_players[n_new_p]; for (pcur=cur_players; pcuractive && pcur->visible) { *end_new = *pcur; n_new_p++; end_new++; } } } /* --- update existing players --- */ for (pcur=cur_players; pcuractive && !strcmp(copy, pcur->name)) { pcur->level = level; if (! pcur->visible) { pcur->visible = 1; pcur->newp = 1; } else if (pcur->newp) { pcur->newp = 0; } } } /* --- check for player already in list --- */ end_new = &new_players[n_new_p]; for (pnew=new_players; pnewactive && !strcmp(copy, pnew->name)) goto maybe_update; } /* --- add player to list --- */ newp = end_new; strcpy(newp->name, copy); newp->active = 1; newp->level = level; newp->newp = 1; newp->visible = 1; n_new_p++; if (n_new_p >= MAX_NEW_P) { n_new_p = 0; newp = &new_players[0]; } end_new = &new_players[n_new_p]; maybe_update: if (mode == 1) { update_players(); } } /* end sta_player() */ /***********************************************************************/ /* sta_passed_on(): mark a recently passed-on player as gone on F keys */ /***********************************************************************/ void sta_passed_on(char *player) { char copy[10], *pcopy; struct player *pcur, *pnew; /* --- if line begins with '|', it was snooped. --- */ /* but we only trust our own QU, so trash it. */ if (player[0] == '|') return; /* --- remove leading garbage from player name. Must start w UC --- */ while (*player && ! isupper(*player)) { player++; } if (! *player) return; /* --- remove trailing garbage (only alpha significant) --- */ for (pcopy=copy; isalpha(*player); player++) { *pcopy++ = *player; } *pcopy = '\0'; if (! copy[0]) return; /* --- copy all old players except deceased to new list --- */ n_new_p = 0; for (pcur=cur_players; pcurname) && pcur->active && pcur->visible) { pnew = end_new; *pnew = *pcur; pnew->visible = 1; pnew->active = 1; n_new_p++; end_new = &new_players[n_new_p]; } } update_players(); } /* end sta_passed_on() */ /***************************************************/ /* sta_repeat(): start or stop keyboard repetition */ /***************************************************/ void sta_repeat(int mode) { if (mode) { repeating = 1; repeat_tix = 0; } else { repeating = 0; } } /* end sta_repeat() */ /***************************************/ /* sta_rwc(): Display real world clock */ /***************************************/ void sta_rwc(char *fmt_str) { win_select(WIN_STAT); win_x(POS_RWC); win_puts(fmt_str); /* --- update stam if sleeping or not in game --- */ if (stam < maxs) { if (playing && sleeping) { sleep_ticks += 10; } else if (! playing) { sleep_ticks += 1; } if (sleep_ticks >= 60) { stam++; sleep_ticks -= 60; sta_stam3(); } } /* --- update BL clock if in game --- */ if (playing) { bl_time++; if ((bl_time % 6) == 0) { bl_ticks = bl_time / 6; sta_blc(); } } /* --- update user function keys --- */ if (in_users) { if (! --in_users) { update_players(); } } } /* end sta_rwc() */ /****************************************/ /* sta_tick(): increment repeat counter */ /****************************************/ void sta_tick() { if (repeating == 2) { if (++repeat_tix > 100) { kbd_repeat(); repeat_tix = 0; repeating = 1; } } else if (looping == 2) { looping = 1; kbd_repeat(); } } /* end sta_tick() */ /*******************************************/ /* sta_star(): announce presence of prompt */ /*******************************************/ void sta_star(void) { if (repeating == 1) { repeating = 2; } else if (looping == 1) { looping = 2; } } /* end sta_star() */ /* EOF(WtSta.C) */