2 * Netris -- A free networked version of Tetris
3 * Copyright (C) 1994,1995 Mark Weaver <Mark_Weaver@brown.edu>
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.26 1995/07/11 08:53:32 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 Mark Weaver <Mark_Weaver@brown.edu>\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 string containing\n"
76 " the keys in order: left, rotate, right, drop,\n"
77 " down-faster, toggle-spying, pause\n"
78 " -i <sec> Set the step-down interval, in seconds\n"
79 " -r <robot> Execute <robot> (a command) as a robot controlling\n"
80 " the game instead of the keyboard\n"
81 " -F Use fair robot interface\n"
82 " -s <seed> Start with given random seed\n"
83 " -D Drops go into drop mode\n"
84 " This means that sliding off a cliff after a drop causes\n"
85 " another drop automatically\n"
86 " -S Disable standout mode (inverse/bold) for slow terminals\n"
87 " -H Show distribution and warranty information\n"
89 version_string, DEFAULT_PORT);
92 ExtFunc void DistInfo(void)
95 "Netris version %s (C) 1994,1995 Mark Weaver <Mark_Weaver@brown.edu>\n"
97 "This program is free software; you can redistribute it and/or modify\n"
98 "it under the terms of the GNU General Public License as published by\n"
99 "the Free Software Foundation; either version 2 of the License, or\n"
100 "(at your option) any later version.\n"
102 "This program is distributed in the hope that it will be useful,\n"
103 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
104 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
105 "GNU General Public License for more details.\n"
107 "You should have received a copy of the GNU General Public License\n"
108 "along with this program; if not, write to the Free Software\n"
109 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n",
113 ExtFunc void Rules(void)
116 "Netris version %s rules\n"
120 "It's just like normal Tetris except that when you clear more than\n"
121 "one row with a single piece, the other player's board is moved up\n"
122 "and junk rows are added to the bottom. If you clear 2, 3 or 4\n"
123 "rows, 1, 2 or 4 junk rows are added to your opponent's board,\n"
124 "respectively. The junk rows have exactly one empty column.\n"
125 "For each group of junk rows given, the empty columns will line\n"
126 "up. This is intentional.\n"
128 "The longest surviving player wins the game.\n"
132 "This mode is currently very boring, because there's no scoring\n"
133 "and it never gets any faster. This will be rectified at some point.\n"
134 "I'm not very motivated to do it right now because I'm sick of one\n"
140 * My really crappy random number generator follows
141 * Should be more than sufficient for our purposes though
143 ExtFunc void SRandom(int seed)
146 myRandSeed = seed % 31751 + 1;
149 ExtFunc int Random(int min, int max1)
151 myRandSeed = (myRandSeed * 31751 + 15437) % 32767;
152 return myRandSeed % (max1 - min) + min;
155 ExtFunc int MyRead(int fd, void *data, int len)
161 result = read(fd, data, left);
163 data = ((char *)data) + result;
166 else if (errno != EINTR)
172 ExtFunc int MyWrite(int fd, void *data, int len)
178 result = write(fd, data, left);
180 data = ((char *)data) + result;
183 else if (errno != EINTR)
189 ExtFunc void NormalizeTime(struct timeval *tv)
191 tv->tv_sec += tv->tv_usec / 1000000;
192 tv->tv_usec %= 1000000;
193 if (tv->tv_usec < 0) {
194 tv->tv_usec += 1000000;
199 ExtFunc void CatchInt(int sig)
204 ExtFunc void CatchAlarm(int sig)
207 signal(SIGALRM, CatchAlarm);
210 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event)
215 ExtFunc long CurTimeval(void)
219 gettimeofday(&tv, NULL);
220 tv.tv_sec -= baseTimeval.tv_sec;
221 tv.tv_usec -= baseTimeval.tv_usec;
222 return GetTimeval(&tv);
225 ExtFunc void SetTimeval(struct timeval *tv, long usec)
227 tv->tv_sec = usec / 1000000;
228 tv->tv_usec = usec % 1000000;
231 ExtFunc long GetTimeval(struct timeval *tv)
233 return tv->tv_sec * 1000000 + tv->tv_usec;
236 static long SetITimer1(long interval, long value)
238 struct itimerval it, old;
240 SetTimeval(&it.it_interval, interval);
241 SetTimeval(&it.it_value, value);
242 if (setitimer(ITIMER_REAL, &it, &old) < 0)
244 signal(SIGALRM, CatchAlarm);
245 return GetTimeval(&old.it_value);
248 ExtFunc long SetITimer(long interval, long value)
252 old = SetITimer1(0, 0);
254 SetITimer1(interval, value);
258 ExtFunc volatile void die(char *msg)
264 ExtFunc volatile void fatal(char *msg)
266 fprintf(stderr, "%s\n", msg);
270 ExtFunc void BlockSignals(MySigSet *saved, ...)
276 va_start(args, saved);
277 #ifdef HAS_SIGPROCMASK
282 while ((sig = va_arg(args, int))) {
283 #ifdef HAS_SIGPROCMASK
284 sigaddset(&set, sig);
289 #ifdef HAS_SIGPROCMASK
290 sigprocmask(SIG_BLOCK, &set, saved);
292 *saved = sigblock(set);
297 ExtFunc void RestoreSignals(MySigSet *saved, MySigSet *set)
299 #ifdef HAS_SIGPROCMASK
300 sigprocmask(SIG_SETMASK, set, saved);
303 *saved = sigsetmask(*set);
309 ExtFunc void AddEventGen(EventGenRec *gen)
311 assert(gen->next == NULL);
312 gen->next = nextGen->next;
316 ExtFunc void RemoveEventGen(EventGenRec *gen)
318 assert(gen->next != NULL);
319 while (nextGen->next != gen)
320 nextGen = nextGen->next;
321 nextGen->next = gen->next;
325 ExtFunc MyEventType WaitMyEvent(MyEvent *event, int mask)
330 int result, anyReady, anySet;
333 /* XXX In certain circumstances, this routine does polling */
335 for (i = 0; i < FT_len; ++i)
337 anyReady = anySet = 0;
340 if (gen->mask & mask) {
344 FD_SET(gen->fd, &fds[gen->fdType]);
349 } while (gen != nextGen);
352 tv.tv_usec = (retry && !anyReady) ? 500000 : 0;
353 result = select(FD_SETSIZE, &fds[FT_read], &fds[FT_write],
354 &fds[FT_except], anyReady ? &tv : NULL);
357 if (retry && !anyReady)
363 if ((gen->mask & mask)
364 && (gen->ready || (result > 0 && gen->fd >= 0
365 && FD_ISSET(gen->fd, &fds[gen->fdType])))) {
367 event->type = gen->func(gen, event);
368 if (event->type != E_none) {
374 } while (gen != nextGen);