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.
25 #include <sys/types.h>
33 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event);
34 static EventGenRec alarmGen = {
35 &alarmGen, 0, FT_read, -1, AlarmGenFunc, EM_alarm
37 static EventGenRec *nextGen = &alarmGen;
39 static int myRandSeed = 1;
41 static long baseTimeval;
44 void AtExit(void (*handler)(void))
47 on_exit((void *)handler, NULL);
53 ///////////// HELP MESSAGES /////////////
58 "NETRIS %s\t(c) 1994-1996,1999 Mark H. Weaver <mhw@netris.org>\n"
59 " \t(c) 2002 Shiar <shiar@shiar.org>\n\n",
67 "This program is free software; you can redistribute it and/or modify\n"
68 "it under the terms of the GNU General Public License as published by\n"
69 "the Free Software Foundation; either version 2 of the License, or\n"
70 "(at your option) any later version.\n"
72 "This program is distributed in the hope that it will be useful,\n"
73 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
74 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
75 "GNU General Public License for more details.\n"
77 "You should have received a copy of the GNU General Public License\n"
78 "along with this program; if not, write to the Free Software\n"
79 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
90 "Good old Tetris. Scoring is like on the GameBoy version (so try to\n"
91 "remove as many lines at once as you can). After removing ten lines\n"
92 "you go to the next level, which will be faster thus making the game\n"
97 "It's just like normal T*tris except that when you clear more than\n"
98 "one row with a single piece, the other player receives penalty lines\n"
99 "For clearing 2, 3 or 4 rows, respectively 1, 2 or 4 junk rows will\n"
100 "be added to the bottom of your opponent's board respectively.\n"
101 "The junk rows have exactly one empty column, which will line up for\n"
104 "The longest surviving player wins the game.\n"
109 ///////////// RANDOM /////////////
112 * My really crappy random number generator follows
113 * Should be more than sufficient for our purposes though
115 void SRandom(int seed)
118 myRandSeed = seed % 31751 + 1;
121 int Random(int min, int max1)
122 { //return a random value
123 myRandSeed = (myRandSeed * 31751 + 15437) % 32767;
124 return myRandSeed % (max1 - min) + min;
127 ///////////// I/O /////////////
129 int MyRead(int fd, void *data, int len)
135 result = read(fd, data, left);
137 data = ((char *)data) + result;
140 else if (errno != EINTR)
146 int MyWrite(int fd, void *data, int len)
152 result = write(fd, data, left);
154 data = ((char *)data) + result;
157 else if (errno != EINTR)
163 ///////////// TIME /////////////
165 void NormalizeTime(struct timeval *tv)
167 tv->tv_sec += tv->tv_usec / 1000000;
168 tv->tv_usec %= 1000000;
169 if (tv->tv_usec < 0) {
170 tv->tv_usec += 1000000;
175 void CatchAlarm(int sig)
178 signal(SIGALRM, CatchAlarm);
181 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event)
186 void SetTimeval(struct timeval *tv, long usec)
188 tv->tv_sec = usec / 1000000;
189 tv->tv_usec = usec % 1000000;
192 long GetTimeval(struct timeval *tv)
194 return tv->tv_sec * 1000000 + tv->tv_usec;
197 long AbsTimeval(void)
201 gettimeofday(&tv, NULL);
202 return GetTimeval(&tv);
205 void ResetBaseTime(void)
207 baseTimeval = AbsTimeval();
212 baseTimeval -= AbsTimeval();
215 void ResumeTime(void)
217 baseTimeval += AbsTimeval();
220 long CurTimeval(void)
224 gettimeofday(&tv, NULL);
225 return GetTimeval(&tv) - baseTimeval;
228 static long SetITimer1(long interval, long value)
230 struct itimerval it, old;
232 SetTimeval(&it.it_interval, interval);
233 SetTimeval(&it.it_value, value);
234 if (setitimer(ITIMER_REAL, &it, &old) < 0)
236 signal(SIGALRM, CatchAlarm);
237 return GetTimeval(&old.it_value);
240 long SetITimer(long interval, long value)
244 old = SetITimer1(0, 0);
246 SetITimer1(interval, value);
250 ///////////// ... /////////////
252 volatile void die(char *msg)
258 volatile void fatal(char *msg)
260 fprintf(stderr, "%s\n", msg);
264 void BlockSignals(MySigSet *saved, ...)
270 va_start(args, saved);
271 #ifdef HAS_SIGPROCMASK
276 while ((sig = va_arg(args, int))) {
277 #ifdef HAS_SIGPROCMASK
278 sigaddset(&set, sig);
283 #ifdef HAS_SIGPROCMASK
284 sigprocmask(SIG_BLOCK, &set, saved);
286 *saved = sigblock(set);
291 void RestoreSignals(MySigSet *saved, MySigSet *set)
293 #ifdef HAS_SIGPROCMASK
294 sigprocmask(SIG_SETMASK, set, saved);
297 *saved = sigsetmask(*set);
303 ///////////// EVENTS /////////////
305 void AddEventGen(EventGenRec *gen)
307 assert(gen->next == NULL);
308 gen->next = nextGen->next;
312 void RemoveEventGen(EventGenRec *gen)
314 // assert(gen->next != NULL); /* Be more forgiving, for SIGINTs */
316 while (nextGen->next != gen)
317 nextGen = nextGen->next;
318 nextGen->next = gen->next;
323 MyEventType WaitMyEvent(MyEvent *event, int mask)
328 int result, anyReady, anySet;
332 for (i = 0; i < FT_len; ++i)
334 anyReady = anySet = 0;
337 if (gen->mask & mask) {
341 FD_SET(gen->fd, &fds[gen->fdType]);
346 } while (gen != nextGen);
349 tv.tv_usec = (retry && !anyReady) ? 500000 : 0;
350 result = select(FD_SETSIZE, &fds[FT_read], &fds[FT_write],
351 &fds[FT_except], anyReady ? &tv : NULL);
354 if (retry && !anyReady)
360 if ((gen->mask & mask) && (gen->ready || (
361 result > 0 && gen->fd >= 0
362 && FD_ISSET(gen->fd, &fds[gen->fdType])
365 event->type = gen->func(gen, event);
366 if (event->type != E_none) {
372 } while (gen != nextGen);