netris version 0.3
[netris.git] / curses.c
1 /*
2  * Netris -- A free networked version of Tetris
3  * Copyright (C) 1994,1995  Mark Weaver <Mark_Weaver@brown.edu>
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  * $Id: curses.c,v 1.29 1995/07/11 08:53:21 mhw Exp $
20  */
21
22 #include "netris.h"
23 #include <sys/types.h>
24 #include <unistd.h>
25 #include <curses.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 static void PlotBlock1(int scr, int y, int x, BlockType type);
30 static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event);
31
32 static EventGenRec keyGen =
33                 { NULL, 0, FT_read, STDIN_FILENO, KeyGenFunc, EM_key };
34
35 static int boardYPos[MAX_SCREENS], boardXPos[MAX_SCREENS];
36 static int statusYPos, statusXPos;
37
38 ExtFunc void InitScreens(void)
39 {
40         MySigSet oldMask;
41
42         BlockSignals(&oldMask, SIGINT, 0);
43         initscr();
44         AtExit(CleanupScreens);
45         RestoreSignals(NULL, &oldMask);
46         cbreak();
47         noecho();
48         AddEventGen(&keyGen);
49         move(0, 0);
50         addstr("Netris ");
51         addstr(version_string);
52         addstr(" (C) 1994,1995  Mark Weaver         "
53                 "\"netris -h\" for more info");
54         statusYPos = 22;
55         statusXPos = 0;
56 }
57
58 ExtFunc void CleanupScreens(void)
59 {
60         RemoveEventGen(&keyGen);
61         endwin();
62 }
63
64 ExtFunc void InitScreen(int scr)
65 {
66         int y, x;
67
68         if (scr == 0)
69                 boardXPos[scr] = 1;
70         else
71                 boardXPos[scr] = boardXPos[scr - 1] +
72                                         2 * boardWidth[scr - 1] + 3;
73         boardYPos[scr] = 22;
74         if (statusXPos < boardXPos[scr] + 2 * boardWidth[scr] + 3)
75                 statusXPos = boardXPos[scr] + 2 * boardWidth[scr] + 3;
76         for (y = boardVisible[scr] - 1; y >= 0; --y) {
77                 move(boardYPos[scr] - y, boardXPos[scr] - 1);
78                 addch('|');
79                 move(boardYPos[scr] - y, boardXPos[scr] + 2 * boardWidth[scr]);
80                 addch('|');
81         }
82         for (y = boardVisible[scr]; y >= -1; y -= boardVisible[scr] + 1) {
83                 move(boardYPos[scr] - y, boardXPos[scr] - 1);
84                 addch('+');
85                 for (x = boardWidth[scr] - 1; x >= 0; --x)
86                         addstr("--");
87                 addch('+');
88         }
89 }
90
91 ExtFunc void CleanupScreen(int scr)
92 {
93 }
94
95 static void PlotBlock1(int scr, int y, int x, BlockType type)
96 {
97         move(boardYPos[scr] - y, boardXPos[scr] + 2 * x);
98         switch (type) {
99                 case BT_none:
100                         addstr("  ");
101                         break;
102                 case -BT_piece1:
103                         if (standoutEnable)
104                                 standout();
105                         addstr("$$");
106                         if (standoutEnable)
107                                 standend();
108                         break;
109                 case BT_piece1:
110                         if (standoutEnable)
111                                 standout();
112                         addstr("[]");
113                         if (standoutEnable)
114                                 standend();
115                         break;
116                 default:
117                         assert(0);
118         }
119 }
120
121 ExtFunc void PlotBlock(int scr, int y, int x, BlockType type)
122 {
123         if (y >= 0 && y < boardVisible[scr] && x >= 0 && x < boardWidth[scr])
124                 PlotBlock1(scr, y, x, type);
125 }
126
127 ExtFunc void PlotUnderline(int scr, int x, int flag)
128 {
129         move(boardYPos[scr] + 1, boardXPos[scr] + 2 * x);
130         addstr(flag ? "==" : "--");
131 }
132
133 ExtFunc void ShowDisplayInfo(void)
134 {
135         move(statusYPos - 9, statusXPos);
136         printw("Seed = %d", initSeed);
137         clrtoeol();
138         move(statusYPos - 8, statusXPos);
139         printw("Speed = %dms", speed / 1000);
140         clrtoeol();
141         if (robotEnable) {
142                 move(statusYPos - 6, statusXPos);
143                 if (fairRobot)
144                         addstr("Controlled by a fair robot");
145                 else
146                         addstr("Controlled by a robot");
147                 clrtoeol();
148         }
149         if (opponentFlags & SCF_usingRobot) {
150                 move(statusYPos - 5, statusXPos);
151                 if (opponentFlags & SCF_fairRobot)
152                         addstr("The opponent is a fair robot");
153                 else
154                         addstr("The opponent is a robot");
155                 clrtoeol();
156         }
157 }
158
159 ExtFunc void UpdateOpponentDisplay(void)
160 {
161         move(1, 0);
162         printw("Playing %s@%s", opponentName, opponentHost);
163         clrtoeol();
164 }
165
166 ExtFunc void ShowPause(int pausedByMe, int pausedByThem)
167 {
168         move(statusYPos - 3, statusXPos);
169         if (pausedByThem)
170                 addstr("Game paused by opponent");
171         else
172                 clrtoeol();
173         move(statusYPos - 2, statusXPos);
174         if (pausedByMe)
175                 addstr("Game paused by you");
176         else
177                 clrtoeol();
178 }
179
180 ExtFunc void Message(char *s)
181 {
182         static int line = 0;
183
184         move(statusYPos - 20 + line, statusXPos);
185         addstr(s);      /* XXX Should truncate long lines */
186         clrtoeol();
187         line = (line + 1) % 10;
188         move(statusYPos - 20 + line, statusXPos);
189         clrtoeol();
190 }
191
192 ExtFunc void RefreshScreen(void)
193 {
194         static char timeStr[2][32];
195         time_t theTime;
196
197         time(&theTime);
198         strftime(timeStr[0], 30, "%I:%M %p", localtime(&theTime));
199         /* Just in case the local curses library sucks */
200         if (strcmp(timeStr[0], timeStr[1]))
201         {
202                 move(statusYPos, statusXPos);
203                 addstr(timeStr[0]);
204                 strcpy(timeStr[1], timeStr[0]);
205         }
206         move(boardYPos[0] + 1, boardXPos[0] + 2 * boardWidth[0] + 1);
207         refresh();
208 }
209
210 static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event)
211 {
212         if (MyRead(gen->fd, &event->u.key, 1))
213                 return E_key;
214         else
215                 return E_none;
216 }
217