2 * Netris -- A free networked version of T*tris
3 * Copyright (C) 1994,1995,1996 Mark H. Weaver <mhw@netris.org>
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.
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.
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.
19 * $Id: util.c,v 1.27 1996/02/09 08:22:23 mhw Exp $
27 #include <sys/types.h>
32 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event);
34 static EventGenRec alarmGen =
35 { &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm };
36 static EventGenRec *nextGen = &alarmGen;
38 static myRandSeed = 1;
40 static struct timeval baseTimeval;
42 ExtFunc void InitUtil(void)
48 signal(SIGINT, CatchInt);
52 ExtFunc void ResetBaseTime(void)
54 gettimeofday(&baseTimeval, NULL);
57 ExtFunc void AtExit(void (*handler)(void))
60 on_exit((void *)handler, NULL);
66 ExtFunc void Usage(void)
69 "Netris version %s (C) 1994,1995,1996 Mark H. Weaver <mhw@netris.org>\n"
70 "Usage: netris <options>\n"
71 " -h Print usage information\n"
72 " -w Wait for connection\n"
73 " -c <host> Initiate connection\n"
74 " -p <port> Set port number (default is %d)\n"
75 " -k <keys> Remap keys. The argument is a prefix of the string\n"
76 " containing the keys in order: left, rotate, right, drop,\n"
77 " down-faster, toggle-spying, pause, faster, redraw.\n"
78 " \"^\" prefixes controls. (default is \"%s\")\n"
79 " -i <sec> Set the step-down interval, in seconds\n"
80 " -r <robot> Execute <robot> (a command) as a robot controlling\n"
81 " the game instead of the keyboard\n"
82 " -F Use fair robot interface\n"
83 " -s <seed> Start with given random seed\n"
84 " -D Drops go into drop mode\n"
85 " This means that sliding off a cliff after a drop causes\n"
86 " another drop automatically\n"
87 " -S Disable standout mode (inverse/bold) for slow terminals\n"
88 " -H Show distribution and warranty information\n"
90 version_string, DEFAULT_PORT, DEFAULT_KEYS);
93 ExtFunc void DistInfo(void)
96 "Netris version %s (C) 1994,1995,1996 Mark H. Weaver <mhw@netris.org>\n"
98 "This program is free software; you can redistribute it and/or modify\n"
99 "it under the terms of the GNU General Public License as published by\n"
100 "the Free Software Foundation; either version 2 of the License, or\n"
101 "(at your option) any later version.\n"
103 "This program is distributed in the hope that it will be useful,\n"
104 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
105 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
106 "GNU General Public License for more details.\n"
108 "You should have received a copy of the GNU General Public License\n"
109 "along with this program; if not, write to the Free Software\n"
110 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n",
114 ExtFunc void Rules(void)
117 "Netris version %s rules\n"
121 "It's just like normal T*tris except that when you clear more than\n"
122 "one row with a single piece, the other player's board is moved up\n"
123 "and junk rows are added to the bottom. If you clear 2, 3 or 4\n"
124 "rows, 1, 2 or 4 junk rows are added to your opponent's board,\n"
125 "respectively. The junk rows have exactly one empty column.\n"
126 "For each group of junk rows given, the empty columns will line\n"
127 "up. This is intentional.\n"
129 "The longest surviving player wins the game.\n"
133 "This mode is currently very boring, because there's no scoring\n"
134 "and it never gets any faster. This will be rectified at some point.\n"
135 "I'm not very motivated to do it right now because I'm sick of one\n"
136 "player T*tris. For now, use the \"f\" key (by default) to make the\n"
137 "game go faster. Speedups cannot be reversed for the remainder of\n"
143 * My really crappy random number generator follows
144 * Should be more than sufficient for our purposes though
146 ExtFunc void SRandom(int seed)
149 myRandSeed = seed % 31751 + 1;
152 ExtFunc int Random(int min, int max1)
154 myRandSeed = (myRandSeed * 31751 + 15437) % 32767;
155 return myRandSeed % (max1 - min) + min;
158 ExtFunc int MyRead(int fd, void *data, int len)
164 result = read(fd, data, left);
166 data = ((char *)data) + result;
169 else if (errno != EINTR)
175 ExtFunc int MyWrite(int fd, void *data, int len)
181 result = write(fd, data, left);
183 data = ((char *)data) + result;
186 else if (errno != EINTR)
192 ExtFunc void NormalizeTime(struct timeval *tv)
194 tv->tv_sec += tv->tv_usec / 1000000;
195 tv->tv_usec %= 1000000;
196 if (tv->tv_usec < 0) {
197 tv->tv_usec += 1000000;
202 ExtFunc void CatchInt(int sig)
207 ExtFunc void CatchAlarm(int sig)
210 signal(SIGALRM, CatchAlarm);
213 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event)
218 ExtFunc long CurTimeval(void)
222 gettimeofday(&tv, NULL);
223 tv.tv_sec -= baseTimeval.tv_sec;
224 tv.tv_usec -= baseTimeval.tv_usec;
225 return GetTimeval(&tv);
228 ExtFunc void SetTimeval(struct timeval *tv, long usec)
230 tv->tv_sec = usec / 1000000;
231 tv->tv_usec = usec % 1000000;
234 ExtFunc long GetTimeval(struct timeval *tv)
236 return tv->tv_sec * 1000000 + tv->tv_usec;
239 static long SetITimer1(long interval, long value)
241 struct itimerval it, old;
243 SetTimeval(&it.it_interval, interval);
244 SetTimeval(&it.it_value, value);
245 if (setitimer(ITIMER_REAL, &it, &old) < 0)
247 signal(SIGALRM, CatchAlarm);
248 return GetTimeval(&old.it_value);
251 ExtFunc long SetITimer(long interval, long value)
255 old = SetITimer1(0, 0);
257 SetITimer1(interval, value);
261 ExtFunc volatile void die(char *msg)
267 ExtFunc volatile void fatal(char *msg)
269 fprintf(stderr, "%s\n", msg);
273 ExtFunc void BlockSignals(MySigSet *saved, ...)
279 va_start(args, saved);
280 #ifdef HAS_SIGPROCMASK
285 while ((sig = va_arg(args, int))) {
286 #ifdef HAS_SIGPROCMASK
287 sigaddset(&set, sig);
292 #ifdef HAS_SIGPROCMASK
293 sigprocmask(SIG_BLOCK, &set, saved);
295 *saved = sigblock(set);
300 ExtFunc void RestoreSignals(MySigSet *saved, MySigSet *set)
302 #ifdef HAS_SIGPROCMASK
303 sigprocmask(SIG_SETMASK, set, saved);
306 *saved = sigsetmask(*set);
312 ExtFunc void AddEventGen(EventGenRec *gen)
314 assert(gen->next == NULL);
315 gen->next = nextGen->next;
319 ExtFunc void RemoveEventGen(EventGenRec *gen)
321 assert(gen->next != NULL);
322 while (nextGen->next != gen)
323 nextGen = nextGen->next;
324 nextGen->next = gen->next;
328 ExtFunc MyEventType WaitMyEvent(MyEvent *event, int mask)
333 int result, anyReady, anySet;
336 /* XXX In certain circumstances, this routine does polling */
338 for (i = 0; i < FT_len; ++i)
340 anyReady = anySet = 0;
343 if (gen->mask & mask) {
347 FD_SET(gen->fd, &fds[gen->fdType]);
352 } while (gen != nextGen);
355 tv.tv_usec = (retry && !anyReady) ? 500000 : 0;
356 result = select(FD_SETSIZE, &fds[FT_read], &fds[FT_write],
357 &fds[FT_except], anyReady ? &tv : NULL);
360 if (retry && !anyReady)
366 if ((gen->mask & mask)
367 && (gen->ready || (result > 0 && gen->fd >= 0
368 && FD_ISSET(gen->fd, &fds[gen->fdType])))) {
370 event->type = gen->func(gen, event);
371 if (event->type != E_none) {
377 } while (gen != nextGen);