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.29 1999/05/16 06:56:33 mhw Exp $
27 #include <sys/types.h>
32 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event);
33 static EventGenRec alarmGen =
34 { &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm };
35 static EventGenRec *nextGen = &alarmGen;
37 static int myRandSeed = 1;
39 static long baseTimeval;
41 ExtFunc void AtExit(void (*handler)(void))
44 on_exit((void *)handler, NULL);
50 ///////////// HELP MESSAGES /////////////
52 ExtFunc void Header(void)
55 "NETRIS %s\t(c) 1994-1996,1999 Mark H. Weaver <mhw@netris.org>\n"
56 " \t(c) 2002 Shiar <shiar@shiar.org>\n\n",
60 ExtFunc void Usage(void)
64 "Usage: netris <options>\n"
66 " -h, --help\t\tPrint this usage information\n"
67 " -H, --info\t\tShow distribution and warranty information\n"
68 " -R, --rules\t\tShow game rules\n"
70 " -S, --slowterm\tDisable inverse/bold/color for slow terminals\n"
71 " -a, --ascii\t\tUse ascii characters\n"
72 " -C, --color=0\t\tDisable color\n"
74 " -c, --connect <host>\tInitiate connection\n"
75 " -p, --port <port>\tSet port number (default is %d)\n"
77 " -t, --team <team>\tJoin a team (don't receive lines from your teammates)\n"
78 " -l, --level <lvl>\tBegin at a higher level (can be used as handicap)\n"
79 " -k, --keys <keys>\tRemap keys (default is \"%s\" for cursors)\n"
80 " -d, --dropmode\tDrops go into drop mode\n"
81 " -D, --instadrop\tInstant drop\n"
83 " -r, --robot <cmd>\tExecute program to control the game instead of keyboard\n"
84 " -F, --fair-robot\tUse fair robot interface\n"
85 "\n", DEFAULT_PORT, DEFAULT_KEYS);
88 ExtFunc void DistInfo(void)
92 "This program is free software; you can redistribute it and/or modify\n"
93 "it under the terms of the GNU General Public License as published by\n"
94 "the Free Software Foundation; either version 2 of the License, or\n"
95 "(at your option) any later version.\n"
97 "This program is distributed in the hope that it will be useful,\n"
98 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
99 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
100 "GNU General Public License for more details.\n"
102 "You should have received a copy of the GNU General Public License\n"
103 "along with this program; if not, write to the Free Software\n"
104 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
108 ExtFunc void Rules(void)
114 "Good old Tetris. Scoring is like on the GameBoy version (so try to\n"
115 "remove as many lines at once as you can). After removing ten lines\n"
116 "you go to the next level, which will be faster thus making the game\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 receives penalty lines\n"
123 "For clearing 2, 3 or 4 rows, respectively 1, 2 or 4 junk rows will\n"
124 "be added to the bottom of your opponent's board respectively.\n"
125 "The junk rows have exactly one empty column, which will line up for\n"
128 "The longest surviving player wins the game.\n"
132 ///////////// RANDOM /////////////
135 * My really crappy random number generator follows
136 * Should be more than sufficient for our purposes though
138 ExtFunc void SRandom(int seed)
141 myRandSeed = seed % 31751 + 1;
144 ExtFunc int Random(int min, int max1)
145 { //return a random value
146 myRandSeed = (myRandSeed * 31751 + 15437) % 32767;
147 return myRandSeed % (max1 - min) + min;
150 ///////////// I/O /////////////
152 ExtFunc int MyRead(int fd, void *data, int len)
158 result = read(fd, data, left);
160 data = ((char *)data) + result;
163 else if (errno != EINTR)
169 ExtFunc int MyWrite(int fd, void *data, int len)
175 result = write(fd, data, left);
177 data = ((char *)data) + result;
180 else if (errno != EINTR)
186 ///////////// TIME /////////////
188 ExtFunc void NormalizeTime(struct timeval *tv)
190 tv->tv_sec += tv->tv_usec / 1000000;
191 tv->tv_usec %= 1000000;
192 if (tv->tv_usec < 0) {
193 tv->tv_usec += 1000000;
198 ExtFunc void CatchAlarm(int sig)
201 signal(SIGALRM, CatchAlarm);
204 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event)
209 ExtFunc void SetTimeval(struct timeval *tv, long usec)
211 tv->tv_sec = usec / 1000000;
212 tv->tv_usec = usec % 1000000;
215 ExtFunc long GetTimeval(struct timeval *tv)
217 return tv->tv_sec * 1000000 + tv->tv_usec;
220 ExtFunc long AbsTimeval(void)
224 gettimeofday(&tv, NULL);
225 return GetTimeval(&tv);
228 ExtFunc void ResetBaseTime(void)
230 baseTimeval = AbsTimeval();
233 ExtFunc void PauseTime(void)
235 baseTimeval -= AbsTimeval();
238 ExtFunc void ResumeTime(void)
240 baseTimeval += AbsTimeval();
243 ExtFunc long CurTimeval(void)
247 gettimeofday(&tv, NULL);
248 return GetTimeval(&tv) - baseTimeval;
251 static long SetITimer1(long interval, long value)
253 struct itimerval it, old;
255 SetTimeval(&it.it_interval, interval);
256 SetTimeval(&it.it_value, value);
257 if (setitimer(ITIMER_REAL, &it, &old) < 0)
259 signal(SIGALRM, CatchAlarm);
260 return GetTimeval(&old.it_value);
263 ExtFunc long SetITimer(long interval, long value)
267 old = SetITimer1(0, 0);
269 SetITimer1(interval, value);
273 ///////////// ... /////////////
275 ExtFunc volatile void die(char *msg)
281 ExtFunc volatile void fatal(char *msg)
283 fprintf(stderr, "%s\n", msg);
287 ExtFunc void BlockSignals(MySigSet *saved, ...)
293 va_start(args, saved);
294 #ifdef HAS_SIGPROCMASK
299 while ((sig = va_arg(args, int))) {
300 #ifdef HAS_SIGPROCMASK
301 sigaddset(&set, sig);
306 #ifdef HAS_SIGPROCMASK
307 sigprocmask(SIG_BLOCK, &set, saved);
309 *saved = sigblock(set);
314 ExtFunc void RestoreSignals(MySigSet *saved, MySigSet *set)
316 #ifdef HAS_SIGPROCMASK
317 sigprocmask(SIG_SETMASK, set, saved);
320 *saved = sigsetmask(*set);
326 ///////////// EVENTS /////////////
328 ExtFunc void AddEventGen(EventGenRec *gen)
330 assert(gen->next == NULL);
331 gen->next = nextGen->next;
335 ExtFunc void RemoveEventGen(EventGenRec *gen)
337 // assert(gen->next != NULL); /* Be more forgiving, for SIGINTs */
339 while (nextGen->next != gen)
340 nextGen = nextGen->next;
341 nextGen->next = gen->next;
346 ExtFunc MyEventType WaitMyEvent(MyEvent *event, int mask)
351 int result, anyReady, anySet;
355 for (i = 0; i < FT_len; ++i)
357 anyReady = anySet = 0;
360 if (gen->mask & mask) {
364 FD_SET(gen->fd, &fds[gen->fdType]);
369 } while (gen != nextGen);
372 tv.tv_usec = (retry && !anyReady) ? 500000 : 0;
373 result = select(FD_SETSIZE, &fds[FT_read], &fds[FT_write],
374 &fds[FT_except], anyReady ? &tv : NULL);
377 if (retry && !anyReady)
383 if ((gen->mask & mask)
384 && (gen->ready || (result > 0 && gen->fd >= 0
385 && FD_ISSET(gen->fd, &fds[gen->fdType])))) {
387 event->type = gen->func(gen, event);
388 if (event->type != E_none) {
394 } while (gen != nextGen);