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 ///////////// CONFIG /////////////
169 file_out = fopen(CONFIG_FILE, "w");
170 if (file_out == NULL) {
171 perror("Error writing config file");
175 fprintf(file_out, "### NETRIS %s Config file ###\n\n", version_string);
178 fprintf(stderr, "Wrote new game configuration to %s\n", CONFIG_FILE);
181 ///////////// TIME /////////////
183 void NormalizeTime(struct timeval *tv)
185 tv->tv_sec += tv->tv_usec / 1000000;
186 tv->tv_usec %= 1000000;
187 if (tv->tv_usec < 0) {
188 tv->tv_usec += 1000000;
193 void CatchAlarm(int sig)
196 signal(SIGALRM, CatchAlarm);
199 static MyEventType AlarmGenFunc(EventGenRec *gen, MyEvent *event)
204 void SetTimeval(struct timeval *tv, long usec)
206 tv->tv_sec = usec / 1000000;
207 tv->tv_usec = usec % 1000000;
210 long GetTimeval(struct timeval *tv)
212 return tv->tv_sec * 1000000 + tv->tv_usec;
215 long AbsTimeval(void)
219 gettimeofday(&tv, NULL);
220 return GetTimeval(&tv);
223 void ResetBaseTime(void)
225 baseTimeval = AbsTimeval();
230 baseTimeval -= AbsTimeval();
233 void ResumeTime(void)
235 baseTimeval += AbsTimeval();
238 long CurTimeval(void)
242 gettimeofday(&tv, NULL);
243 return GetTimeval(&tv) - baseTimeval;
246 static long SetITimer1(long interval, long value)
248 struct itimerval it, old;
250 SetTimeval(&it.it_interval, interval);
251 SetTimeval(&it.it_value, value);
252 if (setitimer(ITIMER_REAL, &it, &old) < 0)
254 signal(SIGALRM, CatchAlarm);
255 return GetTimeval(&old.it_value);
258 long SetITimer(long interval, long value)
262 old = SetITimer1(0, 0);
264 SetITimer1(interval, value);
268 ///////////// ... /////////////
270 volatile void die(char *msg)
276 volatile void fatal(char *msg)
278 fprintf(stderr, "%s\n", msg);
282 void BlockSignals(MySigSet *saved, ...)
288 va_start(args, saved);
289 #ifdef HAS_SIGPROCMASK
294 while ((sig = va_arg(args, int))) {
295 #ifdef HAS_SIGPROCMASK
296 sigaddset(&set, sig);
301 #ifdef HAS_SIGPROCMASK
302 sigprocmask(SIG_BLOCK, &set, saved);
304 *saved = sigblock(set);
309 void RestoreSignals(MySigSet *saved, MySigSet *set)
311 #ifdef HAS_SIGPROCMASK
312 sigprocmask(SIG_SETMASK, set, saved);
315 *saved = sigsetmask(*set);
321 ///////////// EVENTS /////////////
323 void AddEventGen(EventGenRec *gen)
325 assert(gen->next == NULL);
326 gen->next = nextGen->next;
330 void RemoveEventGen(EventGenRec *gen)
332 // assert(gen->next != NULL); /* Be more forgiving, for SIGINTs */
334 while (nextGen->next != gen)
335 nextGen = nextGen->next;
336 nextGen->next = gen->next;
341 MyEventType WaitMyEvent(MyEvent *event, int mask)
346 int result, anyReady, anySet;
350 for (i = 0; i < FT_len; ++i)
352 anyReady = anySet = 0;
355 if (gen->mask & mask) {
359 FD_SET(gen->fd, &fds[gen->fdType]);
364 } while (gen != nextGen);
367 tv.tv_usec = (retry && !anyReady) ? 500000 : 0;
368 result = select(FD_SETSIZE, &fds[FT_read], &fds[FT_write],
369 &fds[FT_except], anyReady ? &tv : NULL);
372 if (retry && !anyReady)
378 if ((gen->mask & mask) && (gen->ready || (
379 result > 0 && gen->fd >= 0
380 && FD_ISSET(gen->fd, &fds[gen->fdType])
383 event->type = gen->func(gen, event);
384 if (event->type != E_none) {
390 } while (gen != nextGen);