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>
35 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event);
36 static EventGenRec alarmGen =
37 { &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm };
38 static EventGenRec *nextGen = &alarmGen;
40 static int myRandSeed = 1;
42 static long baseTimeval;
45 void AtExit(void (*handler)(void))
48 on_exit((void *)handler, NULL);
54 ///////////// HELP MESSAGES /////////////
59 "NETRIS %s\t(c) 1994-1996,1999 Mark H. Weaver <mhw@netris.org>\n"
60 " \t(c) 2002 Shiar <shiar@shiar.org>\n\n",
68 "Usage: netris <options>\n"
70 " -h, --help\t\tPrint this usage information\n"
71 " -H, --info\t\tShow distribution and warranty information\n"
72 " -R, --rules\t\tShow game rules\n"
74 " -S, --slowterm\tDisable inverse/bold/color for slow terminals\n"
75 " -a, --ascii\t\tUse ascii characters\n"
76 " -C, --color=0\t\tDisable color\n"
78 " -c, --connect <host>\tInitiate connection\n"
79 " -p, --port <port>\tSet port number (default is %d)\n"
81 " -t, --team <team>\tJoin a team (don't receive lines from your teammates)\n"
82 " -l, --level <lvl>\tBegin at a higher level (can be used as handicap)\n"
83 " -k, --keys <keys>\tRemap keys (default is \"%s\" for cursors)\n"
84 " -d, --dropmode\tDrops go into drop mode\n"
85 " -D, --instadrop\tInstant drop\n"
87 " -r, --robot <cmd>\tExecute program to control the game instead of keyboard\n"
88 " -F, --fair-robot\tUse fair robot interface\n"
89 "\n", DEFAULT_PORT, DEFAULT_KEYS);
96 "This program is free software; you can redistribute it and/or modify\n"
97 "it under the terms of the GNU General Public License as published by\n"
98 "the Free Software Foundation; either version 2 of the License, or\n"
99 "(at your option) any later version.\n"
101 "This program is distributed in the hope that it will be useful,\n"
102 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
103 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
104 "GNU General Public License for more details.\n"
106 "You should have received a copy of the GNU General Public License\n"
107 "along with this program; if not, write to the Free Software\n"
108 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
118 "Good old Tetris. Scoring is like on the GameBoy version (so try to\n"
119 "remove as many lines at once as you can). After removing ten lines\n"
120 "you go to the next level, which will be faster thus making the game\n"
125 "It's just like normal T*tris except that when you clear more than\n"
126 "one row with a single piece, the other player receives penalty lines\n"
127 "For clearing 2, 3 or 4 rows, respectively 1, 2 or 4 junk rows will\n"
128 "be added to the bottom of your opponent's board respectively.\n"
129 "The junk rows have exactly one empty column, which will line up for\n"
132 "The longest surviving player wins the game.\n"
136 ///////////// RANDOM /////////////
139 * My really crappy random number generator follows
140 * Should be more than sufficient for our purposes though
142 void SRandom(int seed)
145 myRandSeed = seed % 31751 + 1;
148 int Random(int min, int max1)
149 { //return a random value
150 myRandSeed = (myRandSeed * 31751 + 15437) % 32767;
151 return myRandSeed % (max1 - min) + min;
154 ///////////// I/O /////////////
156 int MyRead(int fd, void *data, int len)
162 result = read(fd, data, left);
164 data = ((char *)data) + result;
167 else if (errno != EINTR)
173 int MyWrite(int fd, void *data, int len)
179 result = write(fd, data, left);
181 data = ((char *)data) + result;
184 else if (errno != EINTR)
190 ///////////// TIME /////////////
192 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 void CatchAlarm(int sig)
205 signal(SIGALRM, CatchAlarm);
208 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event)
213 void SetTimeval(struct timeval *tv, long usec)
215 tv->tv_sec = usec / 1000000;
216 tv->tv_usec = usec % 1000000;
219 long GetTimeval(struct timeval *tv)
221 return tv->tv_sec * 1000000 + tv->tv_usec;
224 long AbsTimeval(void)
228 gettimeofday(&tv, NULL);
229 return GetTimeval(&tv);
232 void ResetBaseTime(void)
234 baseTimeval = AbsTimeval();
239 baseTimeval -= AbsTimeval();
242 void ResumeTime(void)
244 baseTimeval += AbsTimeval();
247 long CurTimeval(void)
251 gettimeofday(&tv, NULL);
252 return GetTimeval(&tv) - baseTimeval;
255 static long SetITimer1(long interval, long value)
257 struct itimerval it, old;
259 SetTimeval(&it.it_interval, interval);
260 SetTimeval(&it.it_value, value);
261 if (setitimer(ITIMER_REAL, &it, &old) < 0)
263 signal(SIGALRM, CatchAlarm);
264 return GetTimeval(&old.it_value);
267 long SetITimer(long interval, long value)
271 old = SetITimer1(0, 0);
273 SetITimer1(interval, value);
277 ///////////// ... /////////////
279 volatile void die(char *msg)
285 volatile void fatal(char *msg)
287 fprintf(stderr, "%s\n", msg);
291 void BlockSignals(MySigSet *saved, ...)
297 va_start(args, saved);
298 #ifdef HAS_SIGPROCMASK
303 while ((sig = va_arg(args, int))) {
304 #ifdef HAS_SIGPROCMASK
305 sigaddset(&set, sig);
310 #ifdef HAS_SIGPROCMASK
311 sigprocmask(SIG_BLOCK, &set, saved);
313 *saved = sigblock(set);
318 void RestoreSignals(MySigSet *saved, MySigSet *set)
320 #ifdef HAS_SIGPROCMASK
321 sigprocmask(SIG_SETMASK, set, saved);
324 *saved = sigsetmask(*set);
330 ///////////// EVENTS /////////////
332 void AddEventGen(EventGenRec *gen)
334 assert(gen->next == NULL);
335 gen->next = nextGen->next;
339 void RemoveEventGen(EventGenRec *gen)
341 // assert(gen->next != NULL); /* Be more forgiving, for SIGINTs */
343 while (nextGen->next != gen)
344 nextGen = nextGen->next;
345 nextGen->next = gen->next;
350 MyEventType WaitMyEvent(MyEvent *event, int mask)
355 int result, anyReady, anySet;
359 for (i = 0; i < FT_len; ++i)
361 anyReady = anySet = 0;
364 if (gen->mask & mask) {
368 FD_SET(gen->fd, &fds[gen->fdType]);
373 } while (gen != nextGen);
376 tv.tv_usec = (retry && !anyReady) ? 500000 : 0;
377 result = select(FD_SETSIZE, &fds[FT_read], &fds[FT_write],
378 &fds[FT_except], anyReady ? &tv : NULL);
381 if (retry && !anyReady)
387 if ((gen->mask & mask)
388 && (gen->ready || (result > 0 && gen->fd >= 0
389 && FD_ISSET(gen->fd, &fds[gen->fdType])))) {
391 event->type = gen->func(gen, event);
392 if (event->type != E_none) {
398 } while (gen != nextGen);