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);
95 "This program is free software; you can redistribute it and/or modify\n"
96 "it under the terms of the GNU General Public License as published by\n"
97 "the Free Software Foundation; either version 2 of the License, or\n"
98 "(at your option) any later version.\n"
100 "This program is distributed in the hope that it will be useful,\n"
101 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
102 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
103 "GNU General Public License for more details.\n"
105 "You should have received a copy of the GNU General Public License\n"
106 "along with this program; if not, write to the Free Software\n"
107 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
117 "Good old Tetris. Scoring is like on the GameBoy version (so try to\n"
118 "remove as many lines at once as you can). After removing ten lines\n"
119 "you go to the next level, which will be faster thus making the game\n"
124 "It's just like normal T*tris except that when you clear more than\n"
125 "one row with a single piece, the other player receives penalty lines\n"
126 "For clearing 2, 3 or 4 rows, respectively 1, 2 or 4 junk rows will\n"
127 "be added to the bottom of your opponent's board respectively.\n"
128 "The junk rows have exactly one empty column, which will line up for\n"
131 "The longest surviving player wins the game.\n"
135 ///////////// RANDOM /////////////
138 * My really crappy random number generator follows
139 * Should be more than sufficient for our purposes though
141 void SRandom(int seed)
144 myRandSeed = seed % 31751 + 1;
147 int Random(int min, int max1)
148 { //return a random value
149 myRandSeed = (myRandSeed * 31751 + 15437) % 32767;
150 return myRandSeed % (max1 - min) + min;
153 ///////////// I/O /////////////
155 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 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 ///////////// TIME /////////////
191 void NormalizeTime(struct timeval *tv)
193 tv->tv_sec += tv->tv_usec / 1000000;
194 tv->tv_usec %= 1000000;
195 if (tv->tv_usec < 0) {
196 tv->tv_usec += 1000000;
201 void CatchAlarm(int sig)
204 signal(SIGALRM, CatchAlarm);
207 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event)
212 void SetTimeval(struct timeval *tv, long usec)
214 tv->tv_sec = usec / 1000000;
215 tv->tv_usec = usec % 1000000;
218 long GetTimeval(struct timeval *tv)
220 return tv->tv_sec * 1000000 + tv->tv_usec;
223 long AbsTimeval(void)
227 gettimeofday(&tv, NULL);
228 return GetTimeval(&tv);
231 void ResetBaseTime(void)
233 baseTimeval = AbsTimeval();
238 baseTimeval -= AbsTimeval();
241 void ResumeTime(void)
243 baseTimeval += AbsTimeval();
246 long CurTimeval(void)
250 gettimeofday(&tv, NULL);
251 return GetTimeval(&tv) - baseTimeval;
254 static long SetITimer1(long interval, long value)
256 struct itimerval it, old;
258 SetTimeval(&it.it_interval, interval);
259 SetTimeval(&it.it_value, value);
260 if (setitimer(ITIMER_REAL, &it, &old) < 0)
262 signal(SIGALRM, CatchAlarm);
263 return GetTimeval(&old.it_value);
266 long SetITimer(long interval, long value)
270 old = SetITimer1(0, 0);
272 SetITimer1(interval, value);
276 ///////////// ... /////////////
278 volatile void die(char *msg)
284 volatile void fatal(char *msg)
286 fprintf(stderr, "%s\n", msg);
290 void BlockSignals(MySigSet *saved, ...)
296 va_start(args, saved);
297 #ifdef HAS_SIGPROCMASK
302 while ((sig = va_arg(args, int))) {
303 #ifdef HAS_SIGPROCMASK
304 sigaddset(&set, sig);
309 #ifdef HAS_SIGPROCMASK
310 sigprocmask(SIG_BLOCK, &set, saved);
312 *saved = sigblock(set);
317 void RestoreSignals(MySigSet *saved, MySigSet *set)
319 #ifdef HAS_SIGPROCMASK
320 sigprocmask(SIG_SETMASK, set, saved);
323 *saved = sigsetmask(*set);
329 ///////////// EVENTS /////////////
331 void AddEventGen(EventGenRec *gen)
333 assert(gen->next == NULL);
334 gen->next = nextGen->next;
338 void RemoveEventGen(EventGenRec *gen)
340 // assert(gen->next != NULL); /* Be more forgiving, for SIGINTs */
342 while (nextGen->next != gen)
343 nextGen = nextGen->next;
344 nextGen->next = gen->next;
349 MyEventType WaitMyEvent(MyEvent *event, int mask)
354 int result, anyReady, anySet;
358 for (i = 0; i < FT_len; ++i)
360 anyReady = anySet = 0;
363 if (gen->mask & mask) {
367 FD_SET(gen->fd, &fds[gen->fdType]);
372 } while (gen != nextGen);
375 tv.tv_usec = (retry && !anyReady) ? 500000 : 0;
376 result = select(FD_SETSIZE, &fds[FT_read], &fds[FT_write],
377 &fds[FT_except], anyReady ? &tv : NULL);
380 if (retry && !anyReady)
386 if ((gen->mask & mask) && (gen->ready || (
387 result > 0 && gen->fd >= 0
388 && FD_ISSET(gen->fd, &fds[gen->fdType])
391 event->type = gen->func(gen, event);
392 if (event->type != E_none) {
398 } while (gen != nextGen);