pax_global_header00006660000000000000000000000064134412305160014511gustar00rootroot0000000000000052 comment=d725f51fc626b386feb17da623241bf662f72b41 vitetris-0.58.0/000077500000000000000000000000001344123051600134545ustar00rootroot00000000000000vitetris-0.58.0/.gitignore000066400000000000000000000000071344123051600154410ustar00rootroot00000000000000*.[oa] vitetris-0.58.0/INSTALL000066400000000000000000000023621344123051600145100ustar00rootroot00000000000000INSTALLATION INSTRUCTIONS Linux, *BSD, Mac OS X, etc. --------------------------- Normally, it should be enough to just run: ./configure && make A single executable "tetris" should then have been created, which may be moved anywhere. You can also run "make install" to install the program along with documentation and desktop integration files in /usr/local. If you only get error messages from the shell when you run configure, try to execute with "bash configure" instead. If you don't have bash, you will have to edit config.mk and then run make. Use "./configure help" for a list of build and installation options. If you build with Xlib the game will pause automatically when your terminal window loses focus. By default, vitetris.xpm is installed in pixmapdir and vitetris.desktop in desktopdir. If you don't want them, set those dirs to empty strings with configure or uncomment them in config.mk. That is: ./configure pixmapdir= desktopdir= There is a game server included which can be built with "make gameserver". If SAME_LEVEL_HEIGHT is defined, players will be forced to have the same start level and height (uncomment in src/netw/gameserver.c). See the README under "Network Play" for more information. vitetris-0.58.0/Makefile000066400000000000000000000064401344123051600151200ustar00rootroot00000000000000include config.mk PROGNAME = tetris$(EXE) # Uncomment to change the default. (Only used in Unix-like systems.) #HISCORE_FILENAME = /var/games/vitetris-hiscores INSTALL = install -oroot -groot default: build @echo Done. @echo 'Now run ./$(PROGNAME) (or make install)' $(PROGNAME): $(MAKE) build build: src/src-conf.mk cd src; $(MAKE) tetris mv -f src/tetris$(EXE) $(PROGNAME) @echo stripping symbols to reduce program size: -strip --strip-all $(PROGNAME) gameserver: src/netw/gameserver.c cd src/netw; $(MAKE) gameserver mv -f src/netw/gameserver . src/src-conf.mk: config.mk Makefile src-conf.sh @echo generating $@ ./src-conf.sh '$(CC)' '$(CFLAGS)' '$(CPPFLAGS)' ./src-conf.sh def TWOPLAYER $(TWOPLAYER) ./src-conf.sh obj tetris2p $(TWOPLAYER) ./src-conf.sh def JOYSTICK $(JOYSTICK) ./src-conf.sh obj joylinux $(JOYSTICK) ./src-conf.sh obj select $(UNIX) ./src-conf.sh set BACKEND curses $(CURSES) ./src-conf.sh def CURSES $(CURSES) ./src-conf.sh set CURSES_INC "$(CURSES_INC)" $(CURSES) ./src-conf.sh set BACKEND ansi -z $(CURSES)$(ALLEGRO) ./src-conf.sh set BACKEND allegro $(ALLEGRO) ./src-conf.sh def ALLEGRO $(ALLEGRO) ./src-conf.sh def XLIB $(XLIB) ./src-conf.sh def TERM_RESIZING $(TERM_RESIZING) ./src-conf.sh def NO_MENU -z $(MENU) ./src-conf.sh lib menuext $(MENU) ./src-conf.sh def NO_BLOCKSTYLES -z $(BLOCKSTYLES) ./src-conf.sh lib netw $(NETWORK) ./src-conf.sh def SOCKET $(NETWORK) ./src-conf.sh def INET $(NETWORK) ./src-conf.sh obj inet $(NETWORK) ./src-conf.sh def TTY_SOCKET "$(NETWORK)" -a $(TTY_SOCKET) ./src-conf.sh obj tty_socket "$(NETWORK)" -a $(TTY_SOCKET) ./src-conf.sh set DHISCORE_FILENAME "-D'HISCORE_FILENAME=\"$(HISCORE_FILENAME)\"'" $(HISCORE_FILENAME) ./src-conf.sh def PCTIMER $(PCTIMER) ./src-conf.sh obj pctimer $(PCTIMER) install: $(PROGNAME) $(INSTALL) -d $(DESTDIR)$(bindir) $(DESTDIR)$(docdir) $(INSTALL) -m755 $(PROGNAME) $(DESTDIR)$(bindir) $(INSTALL) -m644 README licence.txt $(DESTDIR)$(docdir) if [ -n "$(pixmapdir)" ]; then \ $(INSTALL) -d $(DESTDIR)$(pixmapdir) && \ $(INSTALL) -m644 vitetris.xpm $(DESTDIR)$(pixmapdir); fi if [ -n "$(desktopdir)" ]; then \ $(INSTALL) -d $(DESTDIR)$(desktopdir) && \ $(INSTALL) -m644 vitetris.desktop $(DESTDIR)$(desktopdir); fi if [ -n "$(ALLEGRO)" ]; then \ $(INSTALL) -d $(DESTDIR)$(datadir) && \ $(INSTALL) -m644 pc8x16.fnt $(DESTDIR)$(datadir); fi @echo Done. @echo You may also wish to create the system-wide highscore file @echo 'with "make install-hiscores"'. install-hiscores: @HS_FN=$(HISCORE_FILENAME); \ if [ -z "$$HS_FN" ]; then HS_FN=/var/games/vitetris-hiscores; fi; \ HS_FN="$(DESTDIR)$$HS_FN"; \ echo $(INSTALL) -d $${HS_FN%/*}; $(INSTALL) -d "$${HS_FN%/*}" && \ echo touch $$HS_FN && touch "$$HS_FN" && \ echo chgrp games $$HS_FN && chgrp games "$$HS_FN" && \ echo chmod g+w $$HS_FN && chmod g+w "$$HS_FN" uninstall: rm -f $(bindir)/$(PROGNAME) rm -f $(docdir)/README rm -f $(docdir)/licence.txt rmdir $(docdir) test -z "$(pixmapdir)" || rm -f $(pixmapdir)/vitetris.xpm -rmdir "$(pixmapdir)" test -z "$(desktopdir)" || rm -f $(desktopdir)/vitetris.desktop -rmdir "$(desktopdir)" -rm -f $(datadir)/pc8x16.fnt -rmdir $(datadir) clean: rm -f systest systest.exe cd src; $(MAKE) clean .PHONY: default build install install-hiscores uninstall clean vitetris-0.58.0/README000066400000000000000000000102421344123051600143330ustar00rootroot00000000000000VITETRIS - Virtual terminal *tris clone Homepage: http://victornils.net/tetris Rotation, scoring, levels and speed should resemble the early Tetris games by Nintendo, with the addition of a short lock delay which makes it possible to play at higher levels. (It does not make it possible to prevent the piece from ever locking by abusing lock delay resets.) vitetris comes with more features and options than might be expected from a simple text mode game. Full input control, customizable appearance, netplay where both players can choose difficulty (level and height) -- unless you must have sound (or just don't like Tetris), you won't be dissappointed. Everything is not described here, but you should be able to figure it out. This program is free software. It is distributed under the terms of a simple BSD-style licence (OSI-approved). See licence.txt for details. How to Play ----------- Run "./tetris" inside a terminal window if you have just extracted a tarball somewhere (cd into the directory first). The command could be "vitetris" or "tetris" if you have used a package manager to install it. (If you're on Windows, just double-click tetris.exe.) To navigate in the menus, use the cursor keys, ENTER to proceed (or leave a menu), and BACKSPACE or ESC to go back. Exit at once with Q. Default Game Controls Move left: LEFT Move right: RIGHT Rotate: UP Softdrop: DOWN Harddrop: SPACE To pause in a single-player game, press P or ENTER. A-type means a normal "marathon" game. In a B-type game, the object is to clear 25 lines. Options ------- The first thing you want to do if you're in a terminal window with a white background is to enter "Options" and set "Term BG" to "white" (press right). Otherwise you'll get a white/grey piece which is hard to see. You can also change the colours of individual pieces in the "Tetromino Colours" menu. To change key bindings, go to "Input Setup". To the left are keys used in menus, to the right in-game keys. Just press the key you want to use. If not explicitly set, the following in-game keys depend on some other key binding (e.g. if UP is used for "Up", it is also used for "Rotate"): Rotate - Up Rot cw - A Rot acw - B Softdrop - Dwn "Rot cw" means "Rotate clockwise" and "acw" anticlockwise. There are three separate configurations, single player, player1 and player2, which include keys, starting level and height, and rotation preference. In netplay, the single player configuration is used. Command Line ------------ Run "tetris -help" (or whatever the command name is) to get a help message with a list of command-line options. If you're on Windows, you need to run this from a cmd window, or a "DOS window". This help message tells you where configuration and highscores are saved. Network Play ------------ To play against someone on the internet, one needs to listen with tetris listen PORT (where PORT is a number, e.g. 34034); the other connects with tetris connect HOSTNAME:PORT HOSTNAME may be an IP address or a hostname. If it is omitted, localhost is used. If the server (the one who listens) has mode set to B-type, such a game will be set up. It is also possible to play using Unix domain sockets, which means that filenames on the local system are used as addresses. The most convenient way to set up such a connection is as follows. Start tetris on two different terminals. Then one player enters "2-Player Game", which will bring up a list of ttys. When the tty of the other player is selected, an invitation will appear on his screen. Gamepad Start Button -------------------- The START button on a gamepad can be mapped to act like the ENTER key. Add the following line below [js0] or [js1] in .vitetris (or vitetris.cfg): start=NUM where NUM is the button number. Credits ------- The original Tetris game was designed and programmed by Alexey Pajitnov in 1985. The wiki at tetrisconcept.com has been a valuable resource. tt "Tetris for Terminals" was written by Mike Taylor in 1989. Hugo Fernbom and Andreas Carlsson have helped me with testing, ideas and feedback. vitetris-0.58.0/changes.txt000066400000000000000000000217771344123051600156430ustar00rootroot000000000000002018-06-28: version 0.57.2 * Update version date printed in command-line help 2018-06-26: version 0.57.1 * Fix next piece disappearing after unpausing * Remove author credits from menu/game 2009-09-13: version 0.57 * Allegro: fixed awkward array overrun when there are more than two joysticks connected. * Fixed awkward bug that prevented the first joystick from showing up in the menus when there are two. * Fixed saved player to joystick section in the configuration file (e.g. if player1 used js0, "player=1" was saved to [js1]). * tmpnam() is not used anymore as I realized how tmpfile() can easily be used instead. * Workarounds for PDCurses in Win 98 (getch() returns strange things). I use PDCurses 3.3, haven't tried the latest version. * Other small fixes. 2009-06-17: version 0.56 * Fixed nondetected invalid lines when decoding highscores. * Renamed icon.xpm to vitetris.xpm and added vitetris.desktop. * Removed useless and confusing --destdir from configure. * Modified Makefile to use DESTDIR. * New installation directories: datarootdir, pixmapdir and desktopdir. 2008-10-24: version 0.55 * Fixed code which assumes that char is signed. * Fixed a few netplay things. * Fixed a few keyboard setup things. * Fixed some other small things. 2008-10-16: version 0.54 * Fixed missing null-byte in string when saving won-lost stats. * Fixed incorrect check when waiting for the first tetromino, which the other player sends. Could end the game before anyone has three wins on a slow connection. * Allegro: Desktop colour depth not used on unix since it seems to cause seg fault on startup (sometimes) on Linux X11. * Netplay connect menu. * Won-lost stats depend on which name you use. * Game server much improved and protocol extended so that clients can get a player list and select an opponent from it. * The protocol allows to set start level and height. A custom server can be built which forces players to have the same level and height. * Many small improvements and fixes of the netplay menus, etc. * Fixed possibly incorrect mode when starting with "nomenu". A version compiled without two-player mode would behave very strange if mode is two-player in configuration file, for example. 2008-10-06: version 0.53 * "connect" accepts space between hostname and port number instead of colon. * If port number is missing, checks /dev etc. instead of just guessing that hostname is a tty. * Fixed seg fault when only port number is specified (introduced in 0.51). * Fixed linking error when inet is disabled in src-conf.mk. * The user is asked to confirm that he wants to close the connection when about to leave the netplay menu. * Fixed some problems with the tty invitation system. * Old tty invitation files are once again removed automatically. This was added in 0.43 but missing in 0.50, apparently. 2008-10-03: version 0.52 * Fixed Makefiles on OS X. * Netplay: Tuned a certain timeout which would close the connection. 2008-09-11: version 0.51 * The last hostname:port used with "connect" is remembered and will be used if "connect" is given no argument. * WIN32: added connect.exe, a simple netplay frontend. * Allegro: fullscreen setting available in Options menu. * Allegro: Alt-Enter toggles fullscreen. * Allegro: Desktop colour depth used. * WIN32-Allegro: stdout emulated when not console application. * WIN32-Allegro: fixed tab-repeat when Alt-tabbing away from and switching back to fullscreen in Windows Vista. * The highscore box shows 5-9 instead of 4-8 when a score is entered at position 8 (for example). * Won-lost stats are saved for players which identify themselves with a name (with -name option). 2008-09-03: version 0.50 The goal for this release was to make everything work under Windows/DOS. And of course I couldn't help but fix many other things along the way, so it took quite some time. Here is an incomplete list of more or less important changes: * Netplay is much more robust. There is basic backward compatibility, but you shouldn't play 0.4x anymore. * It is possible for players to connect to a server instead of directly to one another. A simple game server is included. * Two-player bug fixed: if the game ended just at the last frame of the line clear animation, there would be a freeze or a garbage top up for the other player during the next game. * Two-player bug fixed: if a player received garbage just when he had cleared ALL his blocks, the game would hang. * Players receive the same garbage blocks at beginning if they have the same height. * A game can end in a draw. * There is a drop marker at the bottom (not in an 80x24 terminal). * New block style "brackets" (which gives better contrast in xterm). * Tetromino Colours menu fixed. * Input Setup menu improved. * First letters can be used to navigate in the menus. * Command-line options are more helpful; response is given for invalid arguments, unrecognized options etc. * The Allegro library can be used. * Linux joystick code reads axis events correctly. * Ctrl-Z and \r are not used in encoded highscores anymore. Entries which contain these bytes are duplicated for backward compatibility. * Should work with 16-bit compilers (tested with Turbo C). 2008-06-27: version 0.43 * nosafedrop option mentioned in README finally implemented. * The curses version no longer uses select on the stdin file descriptor to wait for input. (Which was a bad thing to do since curses could read stdin as a stream.) * Time delays are better handled. * Fixed colour issues with pdcurses and possibly other versions of curses. * Old tty invitation files (/tmp/vitetris-*) are now removed automatically. 2008-06-23: version 0.42 A fixed typo caused version 0.41 to _not_ compile with two-player disabled. So I just restored the typo. ;-) I have renamed /var/games/vitetris-hiscore to vitetris-hiscores. Diff the src directory if you feel like. 2008-06-18: version 0.41 * Fixed a bug in the 1-player game menu: shown player options would be uninitialized data in a special case. * Garbage meter is now two characters wide and thus more noticable. * Added #ifdef stuff to draw.c. * Some fine-tuning of the joystick code. * Rewritten strtoval in options.c. * Small update to the README file. * Added CHANGELOG-03x and this file. * --destdir added to configure. 2008-04-27: version 0.40 This is a careful rewrite of much of the code. New features include network play, joystick (gamepad) support on Linux, and the compile-time option to use curses. Command-line options have been extended so that menus don't have to be used; menus can now be disabled at compile time. Version 0.3.6 * Fixed pause bug. * American spelling used when locale is en_US. * Tetromino colours can be changed. * Build-system is more portable. * ESC[G not used anymore as it is not a VT100 escape sequence and is not supported in NetBSD's VT100 emulation. * Fixed buggy use of struct timeval which produced an error on NetBSD. * Beaten highscores at end of list are now removed internally, so no 11th entry will show up after entering a new score. Version 0.3.5 * Start height of random blocks added. * Improved menus. * Command-line option "-nomenu" added, which skips menus. * Terminal resizing better handled. * Fixed time delays in slow terminals (when printing is slow). This problem was observed under cygwin/Win 98 on a 400-MHz Pentium II. * Drops are ignored when piece is at its spawn position, to prevent double-drop mistakes when auto-repeat is fast (or otherwise). * README file changed. Version 0.3.4 * Fixed missing flush of output when winner is shown in 2-player mode. * SIGWINCH signal is now handled, which means that terminal resizing can be detected without using Xlib. * The position line under Top Scores now shows up when score qualifies for the highscore list. Version 0.3.3 * Fixed bugs that cause problems under cygwin and possibly under other systems. * Fixed bug in 1-player mode which caused keys with no action to drop piece one row. * Fixed detection of X window in gnome-terminal. * Output buffering is now used. * Interrupt signal is now handled. * Various other small fixes. * Two-clause BSD-style licence added. Version 0.3.2 * Fixed bug that would cause freeze when softdrop key is held down and softdrop speed is set to 20 (discovered by Andreas Carlsson). This bug is not present in version 0.2.x. * Fixed bug introduced in 0.3.1 which causes term bg to be set to white on every startup. * New tt-bg mode for drawing blocks added. Version 0.3.1 * When a horizontal move fails in levels where fall time < lock delay, it is performed again when piece is moved down by gravity. * tt mode added - blocks can be drawn as in Tetris for Terminals. * Terminal options can be specified on command line. * Command-line option "-hiscore" can be used to merge highscore files. * Listing of command-line options with "-help" added. * Some code cleanup. vitetris-0.58.0/config.mk000066400000000000000000000012561344123051600152560ustar00rootroot00000000000000# config.mk # Included in Makefile and src/Makefile. # This file will be overwritten by the configure script. prefix = /usr/local bindir = $(prefix)/bin datarootdir = $(prefix)/share docdir = $(datarootdir)/doc/vitetris pixmapdir = $(datarootdir)/pixmaps desktopdir = $(datarootdir)/applications datadir = $(datarootdir)/allegro #datadir = $(datarootdir)/allegro/vitetris UNIX = y #EXE = .exe TWOPLAYER = y #JOYSTICK = y NETWORK = y TTY_SOCKET = y TERM_RESIZING = y MENU = y BLOCKSTYLES = y INPUT_SYS = unixterm #CURSES = y #ALLEGRO = y #XLIB = y #XLIB_INC = LDFLAGS = LDLIBS = $(LIBS) # DOS millisecond granularity #PCTIMER = pctime14/gccint8 #PCTIMER_INC = -I../pctime14 vitetris-0.58.0/configure000077500000000000000000000414411344123051600153670ustar00rootroot00000000000000#! /bin/sh # I hope this script will save you the task of editing config.mk manually. # It should work with most sh-compatible shells (perhaps not some very old). # # You may comment out/uncomment any of these lines to change defaults. PREFIX=/usr/local ENABLE_2P=y # 2-player ENABLE_JS=y # joystick ENABLE_NETWORK=y #WITH_CURSES=y WITH_X=y #WITH_ALLEGRO=y ENABLE_TERM_RESIZING=y ENABLE_MENU=y ENABLE_BLOCKSTYLES=y # DOS only PCTIMER=y # defaults are assigned later BINDIR= DATAROOTDIR= DOCDIR= PIXMAPDIR=z DESKTOPDIR=z default_prefix=$PREFIX while [ $# -ge 1 ]; do arg=$1 shift arg=${arg#-} arg=${arg#-} if [ "$arg" = h ] || [ "$arg" = help ] then echo 'Usage: ./configure [OPTION]... [VAR=VALUE]...' echo " Installation directories: --prefix=PREFIX install in PREFIX [$PREFIX] --bindir=DIR executable [PREFIX/bin] --datarootdir=DIR data root [PREFIX/share] --docdir=DIR documentation [DATAROOTDIR/doc/vitetris] --pixmapdir=DIR vitetris.xpm [DATAROOTDIR/pixmaps] --desktopdir=DIR vitetris.desktop [DATAROOTDIR/applications] Build options: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] FEATURE= do not include FEATURE (same as FEATURE=no) FEATURE[=ARG] include FEATURE [ARG=yes] curses=LIB link with filename LIB curses=-lLIB link with library named LIB --with- and --without-FEATURE can also be used. Default features:" FEATURES= for feat in "2player=$ENABLE_2P" "joystick=$ENABLE_JS" \ "network=$ENABLE_NETWORK" "curses=$WITH_CURSES" \ "xlib=$WITH_X" "allegro=$WITH_ALLEGRO" nl \ "term_resizing=$ENABLE_TERM_RESIZING" "menu=$ENABLE_MENU" \ "blockstyles=$ENABLE_BLOCKSTYLES" \ " pctimer=$PCTIMER" nl do if [ "$feat" = nl ]; then echo " $FEATURES" FEATURES= else if [ "$feat" != "${feat%=}" ] then feat="$feat"no else feat=${feat%=*} fi FEATURES="$FEATURES $feat" fi done echo echo These variables are used from the environment: echo ' CC CFLAGS CPPFLAGS LDFLAGS LIBS' echo echo See INSTALL for examples and more details. exit fi case "${arg%%=*}" in prefix) PREFIX=${arg#prefix=}; continue ;; bindir) BINDIR=${arg#bindir=}; continue ;; datarootdir) DATAROOTDIR=${arg#datarootdir=}; continue ;; docdir) DOCDIR=${arg#docdir=}; continue ;; pixmapdir) PIXMAPDIR=${arg#pixmapdir=}; continue ;; desktopdir) DESKTOPDIR=${arg#desktopdir=}; continue ;; CC) export CC=${arg#CC=} continue ;; CFLAGS) export CFLAGS=${arg#CFLAGS=} continue ;; CPPFLAGS) export CPPFLAGS=${arg#CPPFLAGS=} continue ;; LDFLAGS) LDFLAGS=${arg#LDFLAGS=} continue ;; LIBS) LIBS=${arg#LIBS=} continue esac arg=${arg%=yes} with=y if [ -n "${arg##*=}" ]; then with=${arg##*=} if [ "$with" = "${with#-l}" ] && [ "$with" = "${with%.*}" ] then with=y fi fi case "${arg%%-*}" in enable|disable|with|without) feat=${arg#*-} ;; *) feat=$arg esac if [ "$feat" = "$arg" ]; then feat=${feat%no} feat=${feat%n} if [ "$feat" != "${feat%=}" ]; then with= fi feat=${feat%=*} elif [ "$feat" != "${feat%=no}" ]; then feat=${feat%=no} case "${arg%%-*}" in enable|with) with= esac else case "${arg%%-*}" in disable|without) with= esac fi if [ "$feat" != "${feat%=*}" ]; then echo "unrecognized option \"$arg\"" exit 1 fi case "$feat" in 2p*|twoplayer) ENABLE_2P=$with ;; js|joystick) ENABLE_JS=$with ;; net*) ENABLE_NETWORK=$with ;; curses|ncurses) WITH_CURSES=$with ;; x*) WITH_X=$with ;; alleg*) WITH_ALLEGRO=$with ;; term_resiz*) ENABLE_TERM_RESIZING=$with ;; menu) ENABLE_MENU=$with ;; blockstyle*) ENABLE_BLOCKSTYLES=$with ;; pctimer) PCTIMER=$with ;; *) echo "unrecognized option \"$arg\"" exit 1 esac done if [ -z "$ENABLE_2P" ]; then ENABLE_NETWORK= fi if [ -n "$WITH_ALLEGRO" ]; then WITH_CURSES= WITH_X= ENABLE_TERM_RESIZING= fi # change directory arg="$0" if [ "$arg" != "${arg#/}" ]; then dir=${arg%/*} echo cd $dir cd $dir arg= fi while [ "$arg" != "${arg#*/}" ]; do dir=${arg%%/*} if [ -n "$dir" -a "$dir" != . ]; then echo cd $dir cd $dir fi arg=${arg#*/} done # echo -n fix if [ "x`echo -n`" = x-n ]; then n=; c='\c' else n=-n; c= fi if [ -n "$ZSH_VERSION" ]; then emulate sh fi DPREFIX=/usr if [ -n "$DJDIR" ]; then echo "DJDIR is set to $DJDIR" DPREFIX=$DJDIR OS=msdos elif [ -n "$MINGDIR" ]; then echo "MINGDIR is set to $MINGDIR" DPREFIX=$MINGDIR CPPFLAGS="$CPPFLAGS -I$DPREFIX/include" LDFLAGS="$LDFLAGS -L$DPREFIX/lib" OS=win32 fi if [ "$OS" = win32 ]; then LDLIBS=-lwinmm for flag in $CFLAGS x; do if [ x$flag = x-mno-cygwin ]; then if [ -z "$CC" ]; then CC=gcc; fi CC="$CC -mno-cygwin" CFLAGS="${CFLAGS%-mno-cygwin*} ${CFLAGS#*no-cygwin}" fi done elif [ "$OS" != msdos ]; then OS=unix fi if [ $OS != unix ]; then if [ "$PREFIX" = "$default_prefix" ]; then PREFIX=c:/vitetris fi WITH_X= fi if [ -n "$PCTIMER" ] && [ $OS = msdos ]; then echo -n 'checking for pctimer... ' PCTIMER= for dir in pctime14/ "" src/; do if [ -f ${dir}gccint8.c ]; then PCTIMER=${dir}gccint8 echo $PCTIMER.c break fi done if [ -z "$PCTIMER" ]; then echo no fi else PCTIMER= fi file_exists() { for file in $@; do if [ -f $file ]; then return 0 fi done return 1 } check_dynlib() { file_exists $1/lib$2.so* $1/lib$2.dll.a $1/lib$2.dylib } if [ $OS != msdos ] then check_lib() { check_dynlib $1 $2 || test -f $1/lib$2.a } else check_lib() { test -f $1/lib$2.a } fi LIB_SEARCH= for flag in $LDFLAGS ignore-me; do if [ -d "${flag#-L}" ]; then LIB_SEARCH="${flag#-L} $LIB_SEARCH" fi done INC_SEARCH= I= for flag in $CPPFLAGS $CFLAGS ignore-me; do if [ x"$flag" = x-I ]; then I=1 else path= if [ -n "$I" ]; then path="$flag" elif [ x"$flag" != x"${flag#-I}" ]; then path="${flag#-I}" fi I= if [ -d "$path" ]; then INC_SEARCH="$path $INC_SEARCH" fi fi done in_inc_search() { if [ $DPREFIX = /usr ] && [ $path = /usr/include ]; then return 0 fi for path in $INC_SEARCH 1; do if [ $1 = $path ]; then return 0; fi done return 1 } add_path_ldflags() { if [ $DPREFIX = /usr ] && [ ${1#/usr} = /lib ]; then return 1 fi libpath=-L$1 for flag in $LDFLAGS 1; do if [ x"$flag" = x$libpath ]; then libpath= break fi done if [ -n "$libpath" ]; then LDFLAGS="$LDFLAGS $libpath" fi } if [ -n "$ENABLE_JS" ] && [ -z "$WITH_ALLEGRO" ]; then if [ "$OS" != unix ]; then echo joystick not supported ENABLE_JS= else echo $n "checking for linux/joystick.h... $c" linux_inc= for path in $INC_SEARCH /usr/include; do if [ -d $path/linux ]; then linux_inc=$path/linux break fi done if [ -n "$linux_inc" ] && [ -f $linux_inc/joystick.h ]; then echo yes echo $n "checking for linux/input.h... $c" if [ -f $linux_inc/input.h ]; then echo yes else echo no ENABLE_JS= fi else echo no ENABLE_JS= fi fi fi CHECK_CURSES= if [ -n "$WITH_CURSES" ]; then CHECK_CURSES=y # don't check for curses if given curses=-lLIB or curses=LIB. if [ "x$WITH_CURSES" != "x${WITH_CURSES#-l}" ]; then CHECK_CURSES= elif [ "x$WITH_CURSES" != "x${WITH_CURSES%.*}" ] && \ [ -e "$WITH_CURSES" ]; then CHECK_CURSES= fi fi for lib in $LIBS x; do if [ x$lib != x${lib%curses*} ]; then WITH_CURSES=$lib CHECK_CURSES= LIBS="${LIBS%$lib*} ${LIBS#*$lib}" fi done libpath= if [ -n "$CHECK_CURSES" ]; then echo $n "checking for curses... $c" WITH_CURSES= if [ $OS = unix ]; then search="/lib /usr/lib /usr/local/lib" else search=$DPREFIX/lib fi for path in $LIB_SEARCH $search; do for lib in ncurses curses pdcurses; do if check_lib $path $lib; then echo found $lib in $path WITH_CURSES=-l$lib break fi done if [ -n "$WITH_CURSES" ]; then libpath=$path break fi done if [ -z "$WITH_CURSES" ]; then echo no fi fi if [ -n "$WITH_CURSES" ]; then echo $n "checking for curses.h... $c" CURSES_INC= for path in $INC_SEARCH $DPREFIX/include /usr/local/include; do if [ -f $path/ncurses/curses.h ]; then path=$path/ncurses fi if [ -f $path/curses.h ]; then echo found in $path CURSES_INC=$path break fi done if [ -z "$CURSES_INC" ]; then echo no WITH_CURSES= else if in_inc_search $CURSES_INC; then CURSES_INC= else CURSES_INC=-I$CURSES_INC fi if [ -n "$libpath" ]; then add_path_ldflags $libpath ; fi fi fi if [ -n "$WITH_X" ]; then echo $n "checking for Xlib... $c" WITH_X= xpath='/usr /usr/X11R6 /usr/X11 /usr/local /usr/X11R7' search=$LIB_SEARCH for path in $xpath; do search="$search $path/lib" done libpath= for path in $search; do if check_dynlib $path X11; then echo found in $path WITH_X=-lX11 if [ $path != /usr ]; then libpath=$path fi break fi done if [ -z "$WITH_X" ]; then echo no else echo $n "checking for X11/Xlib.h... $c" XLIB_INC= search=$INC_SEARCH for path in $xpath; do search="$search $path/include" done for path in $search; do if [ -f $path/X11/Xlib.h ]; then echo found in $path XLIB_INC=$path break fi done if [ -z "$XLIB_INC" ]; then echo no WITH_X= else if in_inc_search $XLIB_INC; then XLIB_INC= else XLIB_INC=-I$XLIB_INC fi add_path_ldflags $libpath fi fi xpath= fi if [ -n "$WITH_ALLEGRO" ] && [ "x$WITH_ALLEGRO" = "x${WITH_ALLEGRO#-l}" ] then if [ $OS = unix ]; then WITH_ALLEGRO='`allegro-config --libs`' elif [ $OS = win32 ]; then echo -n 'checking for Allegro... ' WITH_ALLEGRO= for path in $LIB_SEARCH $DPREFIX/lib; do for lib in alleg alleg_s; do if check_lib $path $lib; then echo -l$lib WITH_ALLEGRO=-l$lib break fi done if [ -n "$WITH_ALLEGRO" ]; then break ; fi done if [ -z "$WITH_ALLEGRO" ]; then echo not found! echo --- FAILED exit 1 fi else WITH_ALLEGRO=-lalleg fi fi CONIO_H= GETTEXTINFO= echo $n "checking for conio.h... $c" if [ -f $DPREFIX/include/conio.h ]; then echo yes CONIO_H=y echo $n "checking for gettextinfo... $c" if grep gettextinfo $DPREFIX/include/conio.h >/dev/null then echo yes ; GETTEXTINFO=y else echo no fi else echo no fi STDINT_H= INTTYPES_H= SYS_TYPES_H= UINT_LEAST32_T= U_INT32_T= echo $n "checking for stdint.h... $c" if [ -f $DPREFIX/include/stdint.h ]; then echo yes STDINT_H=y UINT_LEAST32_T=y else echo no echo $n "checking for inttypes.h... $c" if [ -f $DPREFIX/include/inttypes.h ]; then INTTYPES_H=y if grep uint_least32_t $DPREFIX/include/inttypes.h >/dev/null then echo yes ; UINT_LEAST32_T=y else echo no uint_least32_t fi else echo no fi fi echo $n "checking for sys/types.h... $c" if [ -f $DPREFIX/include/sys/types.h ]; then SYS_TYPES_H=y if [ -n "$UINT_LEAST32_T" ] then echo yes elif grep u_int32_t $DPREFIX/include/sys/types.h >/dev/null then echo yes ; U_INT32_T=y else echo no u_int32_t fi else echo no fi SYS_SELECT_H= if [ $OS != win32 ]; then echo $n "checking for sys/select.h... $c" if [ -f $DPREFIX/include/sys/select.h ] then echo yes ; SYS_SELECT_H=y else echo no fi fi TTY_SOCKET= if [ $OS = unix ] && [ -n "$ENABLE_NETWORK" ]; then echo $n "checking for sys/un.h... $c" if [ -f /usr/include/sys/un.h ] then echo yes ; TTY_SOCKET=y else echo no fi fi if [ $OS = win32 ] && [ -n "$ENABLE_NETWORK" ]; then echo -n 'checking for wsock32... ' if check_lib $DPREFIX/lib wsock32 then echo yes ; LDLIBS="-lwsock32 $LDLIBS" else echo no fi fi echo $n "updating src/config.h $c" echo '/* Generated by configure */ #ifndef config_h #define config_h ' > config_h.tmp for def in CONIO_H-$CONIO_H GETTEXTINFO-$GETTEXTINFO \ STDINT_H-$STDINT_H INTTYPES_H-$INTTYPES_H \ SYS_TYPES_H-$SYS_TYPES_H UINT_LEAST32_T-$UINT_LEAST32_T \ U_INT32_T-$U_INT32_T SYS_SELECT_H-$SYS_SELECT_H; do if [ -n "${def#*-}" ] then echo "#define HAVE_${def%-*} 1" >> config_h.tmp fi done if [ "x$WITH_ALLEGRO" != "x${WITH_ALLEGRO%_s}" ]; then echo >> config_h.tmp echo '#define ALLEGRO_STATICLINK' >> config_h.tmp fi echo ' #include "config2.h" #endif' >> config_h.tmp if cmp -s src/config.h config_h.tmp; then rm -f config_h.tmp echo '(no update needed, leaving unchanged)' else echo mv -f config_h.tmp src/config.h if [ -f config_h.tmp ]; then echo --- ERROR! Could not update src/config.h exit 1 fi fi # Write config.mk echo $n "updating config.mk $c" echo '# config.mk. Generated by configure.' > configmk.tmp echo '# This file is included in Makefile and src/Makefile.' >> configmk.tmp echo >> configmk.tmp # Default installation directories: if [ $OS = unix ]; then if [ -z "$BINDIR" ] then BINDIR='$(prefix)/bin' fi if [ -z "$DATAROOTDIR" ] then DATAROOTDIR='$(prefix)/share' fi if [ -z "$DOCDIR" ] then DOCDIR='$(datarootdir)/doc/vitetris' fi if [ z = "$PIXMAPDIR" ] then PIXMAPDIR='$(datarootdir)/pixmaps' fi if [ z = "$DESKTOPDIR" ] then DESKTOPDIR='$(datarootdir)/applications' fi else if [ -z "$BINDIR" ]; then BINDIR='$(prefix)'; fi if [ -z "$DOCDIR" ]; then DOCDIR='$(prefix)'; fi PIXMAPDIR= DESKTOPDIR= fi echo prefix = $PREFIX >> configmk.tmp echo bindir = $BINDIR >> configmk.tmp echo datarootdir = $DATAROOTDIR >> configmk.tmp echo "docdir = $DOCDIR" >> configmk.tmp echo "pixmapdir = $PIXMAPDIR" >> configmk.tmp echo "desktopdir = $DESKTOPDIR" >> configmk.tmp if [ $OS = unix ]; then echo >> configmk.tmp echo 'datadir = $(datarootdir)/allegro' >> configmk.tmp echo '#datadir = $(datarootdir)/allegro/vitetris' >> configmk.tmp else echo 'datadir = $(prefix)' >> configmk.tmp fi echo >> configmk.tmp if [ $OS = msdos ]; then echo SHELL = sh >> configmk.tmp fi if [ $OS = unix ]; then echo UNIX = y >> configmk.tmp else echo EXE = .exe >> configmk.tmp fi if [ -n "$CC" ]; then echo "CC = $CC" >> configmk.tmp fi if [ -n "$CFLAGS" ]; then echo "CFLAGS = $CFLAGS" >> configmk.tmp fi if [ -n "$CPPFLAGS" ]; then echo "CPPFLAGS = $CPPFLAGS" >> configmk.tmp fi echo >> configmk.tmp comment_if_empty() { if [ -z "$1" ]; then echo $n "#$c" >> configmk.tmp fi } comment_if_empty $ENABLE_2P echo TWOPLAYER = y >> configmk.tmp comment_if_empty $ENABLE_JS echo JOYSTICK = y >> configmk.tmp comment_if_empty $ENABLE_NETWORK echo NETWORK = y >> configmk.tmp comment_if_empty $TTY_SOCKET echo TTY_SOCKET = y >> configmk.tmp comment_if_empty $ENABLE_TERM_RESIZING echo TERM_RESIZING = y >> configmk.tmp comment_if_empty $ENABLE_MENU echo MENU = y >> configmk.tmp comment_if_empty $ENABLE_BLOCKSTYLES echo BLOCKSTYLES = y >> configmk.tmp echo >> configmk.tmp if [ $OS = unix ]; then if [ -z "${WITH_CURSES}${WITH_ALLEGRO}" ] then echo INPUT_SYS = unixterm >> configmk.tmp else echo '#INPUT_SYS = unixterm' >> configmk.tmp fi elif [ -n "$CONIO_H" ]; then if [ -z "${WITH_CURSES}${WITH_ALLEGRO}" ] then echo INPUT_SYS = conio >> configmk.tmp else echo '#INPUT_SYS = conio' >> configmk.tmp fi fi comment_if_empty $WITH_CURSES echo CURSES = y >> configmk.tmp if [ -n "$WITH_CURSES" ]; then echo CURSES_INC = $CURSES_INC >> configmk.tmp fi comment_if_empty "$WITH_ALLEGRO" echo ALLEGRO = y >> configmk.tmp comment_if_empty $WITH_X echo XLIB = y >> configmk.tmp if [ -n "$WITH_X" ] then echo XLIB_INC = $XLIB_INC >> configmk.tmp else echo '#XLIB_INC =' >> configmk.tmp fi echo LDFLAGS = $LDFLAGS >> configmk.tmp if [ "x$WITH_ALLEGRO" != "x${WITH_ALLEGRO%_s}" ] then echo 'LDLIBS = -lalleg_s -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lole32 -ldinput -lddraw -ldxguid -ldsound' >> configmk.tmp echo 'LDLIBS +=' $LDLIBS '$(LIBS)' >> configmk.tmp else echo 'LDLIBS =' "$WITH_ALLEGRO" $LDLIBS $WITH_CURSES $WITH_X '$(LIBS)' \ >> configmk.tmp fi if [ -n "$LIBS" ]; then echo LIBS = $LIBS >> configmk.tmp fi echo ' # DOS millisecond granularity' >> configmk.tmp if [ -n "$PCTIMER" ]; then echo PCTIMER = $PCTIMER >> configmk.tmp if [ $PCTIMER = ${PCTIMER#*/} ]; then echo PCTIMER_INC = -I.. >> configmk.tmp elif [ $PCTIMER = ${PCTIMER#src/} ]; then echo PCTIMER_INC = -I../${PCTIMER%/*} >> configmk.tmp fi else echo '#PCTIMER = pctime14/gccint8' >> configmk.tmp echo '#PCTIMER_INC = -I../pctime14' >> configmk.tmp fi echo >> configmk.tmp if cmp -s config.mk configmk.tmp; then rm -f configmk.tmp echo '(no update needed, leaving unchanged)' else echo mv -f configmk.tmp config.mk if [ -f configmk.tmp ]; then echo --- ERROR! Could not update config.mk rm -f configmk.tmp exit 1 fi fi echo echo INSTALLATION DIRECTORIES: echo " prefix = $PREFIX" echo " bindir = $BINDIR" echo " datarootdir = $DATAROOTDIR" echo " docdir = $DOCDIR" echo " pixmapdir = $PIXMAPDIR" echo " desktopdir = $DESKTOPDIR" echo echo FEATURES: echo $n " $c" for feat in "2player=$ENABLE_2P" "joystick=$ENABLE_JS" \ "network=$ENABLE_NETWORK" "curses=$WITH_CURSES" \ "xlib=$WITH_X" "allegro=$WITH_ALLEGRO" \ "term_resizing=$ENABLE_TERM_RESIZING" "menu=$ENABLE_MENU" \ "blockstyles=$ENABLE_BLOCKSTYLES" pctimer=$PCTIMER do if [ "$feat" = "${feat%=}" ] then echo $n "${feat%=*} $c" fi done echo echo echo '(If you wish to change anything, run "configure help" for options.)' echo Now run make vitetris-0.58.0/icon.ico000066400000000000000000000163561344123051600151130ustar00rootroot00000000000000h6 ¨ž00¨F( hªªªªªªªUªªªªUUUÿUUUÿUÿÿUUUÿÿUÿUÿÿÿÿÿ ,,,888EEEQQQaaaqqq‚‚‚’’’¢¢¢¶¶¶ËËËãããÿÿÿÿÿAÿ}ÿ¾ÿÿ¾ÿ}ÿAÿÿAÿ}ÿ¾ÿÿÿÿ¾ÿ}ÿAÿAÿ}ÿ¾ÿÿÿÿ¾ÿ}ÿAÿ}}ÿ}žÿ}¾ÿ}ßÿ}ÿß}ÿ¾}ÿž}ÿ}}ÿ}žÿ}¾ÿ}ßÿ}ÿÿ}ÿß}ÿ¾}ÿž}ÿ}žÿ}¾ÿ}ßÿ}ÿÿ}ÿß}ÿ¾}ÿž}ÿ¶¶ÿ¶Çÿ¶Ûÿ¶ëÿ¶ÿë¶ÿÛ¶ÿǶÿ¶¶ÿ¶Çÿ¶Ûÿ¶ëÿ¶ÿÿ¶ÿë¶ÿÛ¶ÿǶÿ¶Çÿ¶Ûÿ¶ëÿ¶ÿÿ¶ÿë¶ÿÛ¶ÿǶqqq8qUqqUq8qqqq8qUqqqqUq8qqq8qUqqqqUq8qq88q8Eq8Uq8aq8qa8qU8qE8q88q8Eq8Uq8aq8qq8qa8qU8qE8q8Eq8Uq8aq8qq8qa8qU8qE8qQQqQYqQaqQiqQqiQqaQqYQqQQqQYqQaqQiqQqqQqiQqaQqYQqQYqQaqQiqQqqQqiQqaQqYQAAA A0AA0A AAAA A0AAAA0A AAA A0AAAA0A AA A (A 0A 8A A8 A0 A( A A (A 0A 8A AA A8 A0 A( A (A 0A 8A AA A8 A0 A( A,,A,0A,4A,<A,A<,A4,A0,A,,A,0A,4A,þ><~~<fffffffffÛÛÛ{|Æ`8lÆÆl8 Æ|þþþþ<~~<~<~~< þ 0`þ`0ÀÀÀþ(lþl(88||þþþþ||88<<<fff$llþlllþll|ÆÂÀ|†Æ|ÂÆ 0`Ɔ8ll8vÜÌÌÌv000` 000000 0 0f<ÿlÌÌþÌÌÌÌÎ8l|ÆÆÆÆÆ|Æ|ÆÆÆÆÆ|`0|ÆÆÆÆÆ|0xÌÌÌÌÌÌÌv`0ÌÌÌÌÌÌvÆÆÆÆÆÆÆ~ xÆ|ÆÆÆÆÆÆÆ|ÆÆÆÆÆÆÆÆÆ|~8ll8|0000`ÀÆÆ|þÀÀÀÀþÀÀÂÆÌ0`܆ >ÀÀÂÆÌ0fΞ><<<6lØl6Øl6lØDDDDDDDDUªUªUªUªUªUªUªUªÝwÝwÝwÝwÝwÝwÝwÝwøøø6666666ö66666666þ66666666øø66666öö666666666666666666666666þö6666666666666öþ6666666þøøøÿÿÿÿ66666667666666666666670??076666666666666÷ÿÿ÷666666666666670766666666ÿÿ66666÷÷66666666ÿÿ6666666ÿÿÿÿ666666666666666??666666666666666ÿ66666666ÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿððððððððððððððððÿÿÿÿÿÿÿvÜØØØÜvxÌÌÌØÌÆÆÆÌþÆÆÀÀÀÀÀÀÀþlllllllþÆ`00`Æþ~ØØØØØpfffff|``ÀvÜ~ffff<~ÛÛÛ~~ÛÛó~`À0``|```0|ÆÆÆÆÆÆÆÆþþþ~ÿ0  0~ 0`0 ~ØØØp~vÜvÜ8ll8 ìll<ØlllllpØ0`Èø|||||||vitetris-0.58.0/src-conf.sh000077500000000000000000000014051344123051600155250ustar00rootroot00000000000000#! /bin/sh # generate src/src-conf.mk TEXT= case "$1" in def) TEXT="D$2 = -D$2=1" ;; obj) TEXT="$2_obj = $2.o" ;; lib) TEXT="$2_lib = $2.a" ;; set) TEXT="$2 = $3" shift esac if [ -n "$TEXT" ] then [ -z "$2$3" ] && exit if [ -n "$3" ] && [ "x$4" = x-a ] then shift; shift fi if [ "x$3" = x-z ] && [ -n "$4" ] then TEXT="#$TEXT" elif [ -z "$3" ] then TEXT="#$TEXT" fi echo $TEXT >> src/src-conf.mk exit fi cd src if [ -n "$1" ] then echo CC = $1 > src-conf.mk else echo > src-conf.mk fi echo 'CCFLAGS = $(CFLAGS) $(CPPFLAGS)' >> src-conf.mk echo '#CFLAGS = -O2 -Wall -pedantic -Wno-parentheses' >> src-conf.mk if [ -n "$2" ] then echo CFLAGS = $2 >> src-conf.mk else echo CFLAGS = -O2 >> src-conf.mk fi [ -n "$3" ] && echo CPPFLAGS = $3 >> src-conf.mk cd .. vitetris-0.58.0/src/000077500000000000000000000000001344123051600142435ustar00rootroot00000000000000vitetris-0.58.0/src/Makefile000066400000000000000000000047311344123051600157100ustar00rootroot00000000000000include ../config.mk include src-conf.mk OBJS = main.o cmdline.o cfgfile.o options.o hiscore.o lang.o \ timer.o $(pctimer_obj) focus.o #OBJS += ../icon.o tetris: $(OBJS) libs ../config.mk $(CC) -o tetris $(OBJS) game.a $(menuext_lib) menu.a $(netw_lib) input.a draw.a textgfx.a $(LDFLAGS) $(LDLIBS) main.o: main.c timer.h cfgfile.h options.h lang.h focus.h \ textgfx/textgfx.h input/input.h game/tetris.h game/game.h \ menu/menuext.h netw/sock.h config.h src-conf.mk $(CC) $(CCFLAGS) -I. $(DTWOPLAYER) $(DSOCKET) $(DINET) $(DTTY_SOCKET) $(DNO_MENU) $(DTERM_RESIZING) $(DXLIB) $(DALLEGRO) -c main.c #cmdline.o: cmdline-empty.c # $(CC) $(CCFLAGS) -c -ocmdline.o cmdline-empty.c cmdline.o: cmdline.c version.h config.h config2.h options.h cfgfile.h \ lang.h game/game.h textgfx/textgfx.h src-conf.mk $(CC) $(CCFLAGS) -I. $(DTWOPLAYER) $(DJOYSTICK) $(DCURSES) $(DALLEGRO) $(DSOCKET) $(DINET) $(DTTY_SOCKET) $(DNO_MENU) $(DNO_BLOCKSTYLES) $(DHISCORE_FILENAME) -c cmdline.c cfgfile.o: cfgfile.c cfgfile.h options.h hiscore.h input/input.h \ input/keyboard.h input/joystick.h draw/draw.h src-conf.mk $(CC) $(CCFLAGS) -I. $(DTWOPLAYER) $(DJOYSTICK) $(DCURSES) $(DALLEGRO) -c cfgfile.c options.o: options.c options.h hiscore.o: hiscore.c hiscore.h cfgfile.h lang.h game/tetris.h src-conf.mk $(CC) $(CCFLAGS) -I. $(DHISCORE_FILENAME) -c hiscore.c lang.o: lang.c lang.h timer.o: timer.c timer.h pctimer.h config.h config2.h ../config.mk src-conf.mk $(CC) $(CCFLAGS) $(DPCTIMER) $(PCTIMER_INC) $(DALLEGRO) -c timer.c pctimer.o: ../$(PCTIMER).c ../$(PCTIMER).h ../config.mk src-conf.mk $(CC) $(CCFLAGS) $(PCTIMER_INC) -c -opctimer.o ../$(PCTIMER).c focus.o: focus.c focus.h ../config.mk src-conf.mk $(CC) $(CCFLAGS) $(DXLIB) $(XLIB_INC) $(DALLEGRO) -c focus.c ../icon.o: ../icon.rc cd ..; windres icon.rc icon.o .c.o: $(CC) $(CCFLAGS) -c $< libs: gamea menua netwa inputa drawa textgfxa mv -f game/game.a . mv -f menu/*.a . -mv -f netw/netw.a . mv -f input/input.a . mv -f draw/draw.a . mv -f textgfx/textgfx.a . gamea: $(MAKE) -Cgame menua: $(MAKE) -Cmenu netwa: $(MAKE) -Cnetw inputa: $(MAKE) -Cinput $(INPUT_SYS) drawa: $(MAKE) -Cdraw textgfxa: $(MAKE) -Ctextgfx clean: rm -f tetris tetris.exe $(OBJS) pctimer.o rm -f game.a menu.a menuext.a netw.a input.a draw.a textgfx.a $(MAKE) -Cgame clean $(MAKE) -Cmenu clean $(MAKE) -Cnetw clean $(MAKE) -Cinput clean $(MAKE) -Cdraw clean $(MAKE) -Ctextgfx clean .PHONY: libs gamea menua netwa inputa drawa textgfxa clean vitetris-0.58.0/src/cfgfile.c000066400000000000000000000205041344123051600160070ustar00rootroot00000000000000#include #include #include #include "config.h" #ifdef UNIX #include #include #include #include #endif #include "cfgfile.h" #include "options.h" #include "hiscore.h" #include "input/input.h" #include "input/keyboard.h" #include "input/joystick.h" #include "draw/draw.h" char cfgfilename[80] = CONFIG_FILENAME; static const char input_keynames[12][6] = { "left", "right", "up", "down", "a", "b", "start", "rot", "sdrop", "rot-a", "rot-b", "hdrop" }; static const char tcolor_keys[8] = "ijlostz"; void writehiscores(FILE *fp); void setcfgfilename(const char *argv0) { #ifdef UNIX struct passwd *pwd; const char *s = getenv("HOME"); if (!s && (pwd = getpwuid(getuid()))) s = pwd->pw_dir; if (s && strlen(s)+strlen(CONFIG_FILENAME) < 79) { strcpy(cfgfilename, s); strcat(cfgfilename, "/"CONFIG_FILENAME); } #else int n = strlen(argv0); do n--; while (n>=0 && argv0[n] !='\\' && argv0[n] !='/'); if (n>=0 && n+strlen(CONFIG_FILENAME) < 79) { strncpy(cfgfilename, argv0, n+1); cfgfilename[n+1] = '\0'; strcat(cfgfilename, CONFIG_FILENAME); } #endif } static int readname(const char *line, char *dest) { int i, n; if (line[0] == '[') { line++; n = 7; } else n = 11; i = 0; while (i < n && (i && line[i] == '-' || islower(line[i]) || isdigit(line[i]))) { dest[i] = line[i]; i++; } if (!i || line[i-1] == '-') return 0; dest[i] = '\0'; if (n == 7) { if (line[i] != ']') return 0; } else { while (isspace(line[i])) i++; if (line[i] != '=') return 0; } return 1; } static int readopt(const char *line, char *key, union val *val, int *tp) { char *p; if (line[0] == '\n') return 0; if (readname(line, key)) { if (line[0] == '[') return 1; if (p = strchr(line, '=')) { *tp = strtoval(p+1, val); return 1; } } return 0; } #if JOYSTICK && TWOPLAYER static void read_inputdev_player(int pl) { int i = 0; if (pl != 1 && pl != 2) return; if (sect_hd.next->name[0] == 'j') i = sect_hd.next->name[2]-'0'+1; inputdevs_player[i] = pl; } #endif static int nametokeypress_i(int i, int flags) { if (i < 6) return MVLEFT+i | flags; #ifdef JOYSTICK if (i == 6) return STARTBTN; #endif if (i == 12) return 0; return (i < 11 ? MVUP+i-7 : HARDDROP) | IN_GAME | flags; } static int nametokeypress(char *name) { int i = 0; int flags; #ifdef TWOPLAYER if (name[0] == 'p') { flags = (name[1]=='1') ? PLAYER_1 : PLAYER_2; memmove(name, name+2, strlen(name+2)+1); } else #endif flags = 0; while (strcmp(name, input_keynames[i]) && i < 12) i++; return nametokeypress_i(i, flags); } static int test_input_chr9(const char *s) { int i = 0; while (i < 9) { if (!strcmp(s, input_chr9[i])) return i+1; i++; } return 0; } static unsigned char *stdin_convertval(union val *val, int tp) { unsigned char bs[2] = ""; if (!tp) { if (val->integ < 0) ; else if (val->integ < 10) bs[0] = val->integ+'0'; else if (val->integ > ' ') { #ifdef CURSES bs[0] = val->integ & 0xFF; bs[1] = val->integ >> 8; #else return NULL; #endif } else bs[0] = val->integ; } else { if (tp == 2) strncpy(val->str, val->p, 4); if (!val->str[1]) return (unsigned char *) val->str; #if !CURSES if (val->str[0] == ESC) return (unsigned char *) val->str; else if (!val->str[3] && sscanf(val->str, "0%X", &tp) == 1) bs[1] = tp; #endif else { bs[0] = test_input_chr9(val->str); if (!bs[0]) return NULL; } } memcpy(val->str, bs, 2); return (unsigned char *) val->str; } static int readkeymapping(char *key, union val val, int tp) { int keypress = nametokeypress(key); unsigned char *input; if (!keypress) return 0; #ifdef JOYSTICK if (sect_hd.next->name[0] == 'j') { if (!tp) val.integ += '0'; else if (tp != 1 || !(val.integ = test_input_chr9(val.str))) return 0; keypress &= 63 | IN_GAME; js_setmapping(sect_hd.next->name[2]=='1', val.integ, keypress); } else #endif if ((keypress & 63) == STARTBTN) ; else if (input = stdin_convertval(&val, tp)) { if (input[0] | input[1]) kb_setmapping(input, keypress); } else return 0; return 1; } static void read_tetrom_color(const char *key, int val) { char *p; if (strlen(key) > 1 || val < 1 || val > 7) return; if (p = strchr(tcolor_keys, key[0])) tetrom_colors[p-tcolor_keys] = val; } static int is_inputconf(const char *key) { return !strcmp(key, "stdin") #ifdef JOYSTICK || !strcmp(key, "js0") || !strcmp(key, "js1") #endif ; } void readoptions() { FILE *fp; char line[80]; char key[12]; union val val; int tp; char inputconf = 0; char tcolors = 0; if (sect_hd.opts || sect_hd.next) return; fp = fopen(cfgfilename, "r"); if (!fp) return; while (fgets(line, 80, fp)) { if (!readopt(line, key, &val, &tp)) continue; if (line[0] == '[') { if (!strcmp(key, "hiscore")) break; inputconf = is_inputconf(key); tcolors = !strcmp(key, "tcolors"); if (!tcolors) addsect(key); continue; } if (inputconf) { #if JOYSTICK && TWOPLAYER if (!tp && !strcmp(key, "player")) read_inputdev_player(val.integ); else #endif if (!readkeymapping(key, val, tp)) goto addopt; continue; } else if (tcolors) { read_tetrom_color(key, val.integ); continue; } addopt: addopt(key, val, tp, sect_hd.next); } fclose(fp); } static void writeopts(FILE *fp, const struct sect *sect) { struct option *o = sect->opts; while (o) { fprintf(fp, "%s=", opt_key(o)); if (opt_isint(o)) fprintf(fp, "%d", o->val.integ); else if (o->val.str[3]) fputs(opt_longstr(o), fp); else fputs(o->val.str, fp); putc('\n', fp); o = o->next; } } #ifdef JOYSTICK static void printbtnmapping(FILE *fp, int n, int keypress, int i) { int b = js_getbtnfor(n, keypress); if (!b || b == keypress) return; keypress ^= IN_GAME; if (b == keypress && b == js_getbtnfor(n, keypress)) return; fprintf(fp, "%s=", input_keynames[i]); if (b < 10) fprintf(fp, "%s", input_chr9[b-1]); else fprintf(fp, "%d", b-'0'); putc('\n', fp); } #else #define printbtnmapping(fp, n, k, i) #endif static void printkeymapping(FILE *fp, int keypress, int i) { unsigned char s[5] = ""; int n = kb_getkeyfor(keypress, s, 0); if (!n) return; #ifdef TWOPLAYER if (keypress & (PLAYER_1 | PLAYER_2)) fprintf(fp, "p%c", '1'+!(keypress & PLAYER_1)); #endif fprintf(fp, "%s=", input_keynames[i]); if (n > 1) { #if CURSES n = s[0]; n |= s[1] << 8; fprintf(fp, "%d", n); #else if (s[0]) fputs(s, fp); else fprintf(fp, "0%X", s[1]); #endif putc('\n', fp); return; } if (s[0] > ' ') putc(s[0], fp); else if (s[0] < 10) fprintf(fp, "%s", input_chr9[s[0]-1]); else fprintf(fp, "%d", s[0]); putc('\n', fp); } #if JOYSTICK #define isjoystick (devkey[0]=='j') #else #define isjoystick 0 #endif static void writeinputconf(FILE *fp, const char *devkey) { int keypress, flags = 0; int i = 0; if (isjoystick) i = devkey[2]-'0'+1; #if JOYSTICK && TWOPLAYER if (inputdevs_player[i]) fprintf(fp, "player=%d\n", inputdevs_player[i]); #endif mappings: i = -1; do { if (i == 5 && !isjoystick || i == 7) i += 2; else if (i == 11) i = 8; else i++; keypress = nametokeypress_i(i, flags); if (isjoystick) printbtnmapping(fp, devkey[2]=='1', keypress, i); else printkeymapping(fp, keypress, i); } while (i != 8); if (isjoystick) return; #ifdef TWOPLAYER if (!flags) { flags = PLAYER_1; goto mappings; } if (flags & PLAYER_1) { flags = PLAYER_2; goto mappings; } #endif } static void write_tetrom_colors(FILE *fp) { int i; if (!strncmp(tetrom_colors, "\x1\x7\x5\x4\x2\x3\x6", 7)) return; fprintf(fp, "[tcolors]\n"); for (i = 0; i < 7; i++) fprintf(fp, "%c=%d\n", tcolor_keys[i], tetrom_colors[i]); } int writeconfig() { FILE *fp; struct sect *sect; readoptions(); readhiscores(NULL); fp = fopen(cfgfilename, "w"); if (!fp) return 0; writeopts(fp, §_hd); addsect("stdin"); #if ALLEGRO addsect("js0"); addsect("js1"); #endif sect = sect_hd.next; while (sect) { fprintf(fp, "[%s]\n", sect->name); if (is_inputconf(sect->name)) writeinputconf(fp, sect->name); writeopts(fp, sect); sect = sect->next; } freeoptions(""); write_tetrom_colors(fp); if (hiscores[0].score) { fprintf(fp, "[hiscore]\n"); writehiscores(fp); } fclose(fp); return 1; } void writeconfig_message() { if (!writeconfig()) printf("ERROR! Could not save configuration to %s\n", cfgfilename); } vitetris-0.58.0/src/cfgfile.h000066400000000000000000000003551344123051600160160ustar00rootroot00000000000000extern char cfgfilename[80]; void setcfgfilename(const char *argv0); void readoptions(); /* returns 1 if file was written, 0 otherwise */ int writeconfig(); /* prints error message to stdout on failure */ void writeconfig_message(); vitetris-0.58.0/src/cmdline-empty.c000066400000000000000000000000461344123051600171560ustar00rootroot00000000000000void proc_args(char **args, int n) {} vitetris-0.58.0/src/cmdline.c000066400000000000000000000332341344123051600160270ustar00rootroot00000000000000#include #include #include #include #include "config.h" #ifdef HAVE_CONIO_H #include /* getch */ #endif #ifdef TTY_SOCKET #include #include #include #endif #include "version.h" #include "cfgfile.h" #include "lang.h" #include "options.h" #include "hiscore.h" #include "game/game.h" #include "game/tetris.h" /* MODE_BTYPE */ #include "textgfx/textgfx.h" #include "input/input.h" #include "menu/menu.h" /* inputsetup_menu */ #include "input/joystick.h" /* js_open */ #include "netw/sock.h" struct cmdopt { const char *pattern; int (*func)(const char *name, char *arg); }; #if ALLEGRO && WIN32 && !ALLEGRO_USE_CONSOLE static int print_stdout_exit(int code) { textgfx_init(); init_inputdevs(); getkeypress_block(0); textgfx_end(); exit(code); } #else #define print_stdout_exit(code) exit(code) #endif static int subexplen(const char *s) { int n = 0; while (s[n] && s[n] != '|') n++; return n; } static int charmatches(int c, const char *charclass) { do { charclass++; if (c == *charclass) return 1; } while (*charclass != ']'); return 0; } static int namematches(const char *name, const char *pattern) { int n; while (n = subexplen(pattern)) { if (*pattern =='[' && !name[1]) { if (charmatches(*name, pattern)) return 1; } else if (!strncmp(name, pattern, n) && n == strlen(name)) return 1; pattern += n; if (*pattern =='|') pattern++; } return 0; } static int argtonum(const char *arg) { if (arg) { while (isspace(*arg)) arg++; if (isdigit(*arg)) return atoi(arg); } return -1; } static void x_arg_error(const char *x, const char *name, const char *try) { printf("%s argument for option \"%s\". ", x, name); puts(try); print_stdout_exit(1); } static void invalid_arg(const char *name, const char *try) { x_arg_error("Invalid", name, try); } static void requires_arg(const char *name, char *arg, const char *try) { if (!arg) x_arg_error("Missing", name, try); } static void set_mode_btype() { union val v; v.integ = getopt_int("", "mode") | MODE_BTYPE; setoption("", "mode", v, 0); } static int cmd_game_opt(const char *name, char *arg) { const char *key = name; int val; int pl = 0; const char *sect = ""; union val v; val = argtonum(arg); #ifdef TWOPLAYER if (*key =='p') { pl = key[1]-'0'; switch (pl) { case 1: sect = "player1"; break; case 2: sect = "player2"; break; default: return 0; } key += 2; } #endif switch (testgameopt(key, val, pl)) { case -1: if (!strcmp(name, "height")) return 0; invalid_arg(name, "Try -help game."); print_stdout_exit(1); case 0: return 0; case 1: if (arg[1] =='b') val |= MODE_BTYPE; break; case 4: set_mode_btype(); } v.integ = val; setoption(sect, key, v, 0); return 1; } static int cmd_wh(const char *name, char *arg) { int n; if ((!arg || islower(*arg)) && !strcmp(name, "h")) return 0; n = argtonum(arg); if (n < 0) invalid_arg(name, ""); if (*name =='w') settermwidth(n); else settermheight(n); return 1; } static void print_opt(char *buf, int tabw, const char *a) { int n = 0; char *p; p = strchr(buf, '\t'); if (!p) { printf(" -"); p = buf; } else { *p = '\0'; p++; if (buf[0]) n = printf(" -%s ", buf); if (n > tabw) { putchar('\n'); n = 0; } do putchar(' '); while (++n < tabw); } printf(p, a); putchar('.'); } static void printopts(int tabw, const char *a, const char *s) { char buf[80]; const char *p; while (*s) { p = strchr(s, '\n'); if (p) { memcpy(buf, s, p-s); buf[p-s] = '\0'; s = p+1; } else { strcpy(buf, s); s = ""; } if (buf[0]) print_opt(buf, tabw, a); putchar('\n'); } } static void printhelp() { printf(VITETRIS_VER" ("VERSION_DATE")" #if WIN32 " WIN32" #elif MSDOS " MSDOS" #endif "\n\n"); printopts(18, NULL, #ifdef ALLEGRO "fullscreen Fullscreen mode\n" "fullscreen 0 Windowed mode\n" #endif #ifndef NO_MENU "nomenu Skip menus\n" #endif "hiscores Print highscore list and exit\n" "hiscores FILE Read and add highscore entries from FILE\n" #if NO_MENU && JOYSTICK "inputsetup [N] Set keys/buttons for player N\n" #elif NO_MENU "inputsetup [N] Set keys for player N\n" #endif #if JOYSTICK && !ALLEGRO "js0 DEVNAME Joystick device name (e.g. /dev/js0)\n" "js1 DEVNAME Second joystick device name\n" #endif ); #ifdef SOCKET printopts(18, "Connect to ", # ifdef INET "listen PORT Listen for connections on port PORT\n" "connect HOSTNAME:PORT" " %sHOSTNAME on PORT. HOSTNAME may be an IP address\n" "connect PORT %slocalhost on PORT\n" # endif # ifdef TTY_SOCKET "listen Listen for local (Unix domain socket) connections\n" "connect TTY %sTTY (e.g. pts/0)\n" # endif "name NAME Identify yourself as NAME when connecting to other players" ); #endif printopts(18, "options and exit", "help Print this help and exit\n" "help game List game %s\n" "help term List terminal %s\n" "?, -h [ARG]\tSame as -help ARG (if ARG isn't a number)"); printf("\n" "Options may also be given as option=ARG, --option=ARG etc.\n\n" "Highscores are saved in %s" #ifdef UNIX ",\nand in "HISCORE_FILENAME" if it exists and is writable" #endif ".\n", cfgfilename); } static void printhelp_game() { puts("Game options:"); printopts(15, "Single-player game", "mode 1 %s\n" "mode 1b %s in B-type mode\n" "level 0-9 Starting level\n" "height 0-5 Height of garbage blocks at beginning\n" "lines N Lines limit (B-type mode)\n" "rotate 0-3 Rotation system\n" "softdrop N Softdrop speed (drop N rows)\n" #ifdef TWOPLAYER "mode 2[b] Two-player game [B-type mode]\n" " Player options are prefixed with p1 or p2 (e.g. -p1level 9)" #endif ); } static void printhelp_term() { char colors[8] = "colours"; char alt[12] = "alternative"; spellword(colors); spellword(alt); puts("Terminal options:"); printopts(14, colors, "w, -width N Set width to N columns (N >= 32)\n" "h, -height N Set height to N lines (N >= 20)\n" "bg black Adjust to dark background\n" "bg white Adjust to light background\n" "color Use %s\n" "mono Don't use %s"); printopts(14, alt, "ascii Use ASCII characters for line drawing\n" "vt100 Use %s character set for line drawing\n" #ifndef NO_BLOCKSTYLES "block STR Draw blocks using characters in STR\n" "tt Draw blocks as in Mike Taylor's Tetris for Terminals\n" "tt-bg tt block characters with background" #endif ); } static int cmd_help(const char *name, char *arg) { if (arg) { if (!strcmp(arg, "game")) { printhelp_game(); print_stdout_exit(0); } if (!strcmp(arg, "term")) { printhelp_term(); print_stdout_exit(0); } if (*name =='h' && !name[1] && argtonum(arg) > -1) return 0; } printhelp(); print_stdout_exit(0); } #ifdef ALLEGRO static int cmd_fullscreen(const char *name, char *arg) { union val v; v.integ = argtonum(arg) != 0; setoption("", "fullscreen", v, 0); return 1; } #endif static int cmd_nomenu(const char *name, char *arg) { #ifndef NO_MENU in_menu = !argtonum(arg); #endif return 1; } static void print_hiscorelist() { char buf[320]; if (!readhiscores(NULL)) puts("No saved scores"); else { printf(" Name Score Lvl Lines\n"); gethiscorelist(buf); printf("%s", buf); } } static int cmd_hiscore(const char *name, char *fname) { if (!fname) { print_hiscorelist(); print_stdout_exit(0); } readhiscores(fname); return 1; } #ifdef NO_MENU static int cmd_inputsetup(const char *name, char *arg) { const char *plstr = "single player"; int pl = argtonum(arg); if (pl < 0 || pl > 2) pl = 0; gettermoptions(); textgfx_init(); atexit(textgfx_end); init_inputdevs(); #ifdef TWOPLAYER switch (pl) { case 1: plstr = "player1"; break; case 2: plstr = "player2"; } #endif printstr(plstr); newln(0); newln(0); inputsetup_menu(pl, 2, 2); textgfx_end(); writeconfig_message(); exit(0); } #endif /* NO_MENU */ #if JOYSTICK && !ALLEGRO static int cmd_jsopen(const char *name, char *arg) { requires_arg(name, arg, ""); js_open(name[2]-'0', arg); return 1; } #endif #ifdef SOCKET static int test_port_number(int n) { if (n > 0xFFFF) { puts("Port number can't be greater than 65535."); print_stdout_exit(1); } return n > 0; } static void press_any_key() { #ifdef HAVE_CONIO_H printf("Press any key to continue "); getch(); putchar('\n'); #else printf("Press ENTER to continue "); getchar(); #endif } static int cmd_listen(const char *name, char *arg) { char *msg; unsigned port = 34034; int n; #ifndef INET if (arg) { printf("Option \"%s\" doesn't allow an argument. ", name); puts("Try -help for more information."); print_stdout_exit(1); } #endif #ifdef TTY_SOCKET if (!arg) { if (msg = mksocket_local(NULL, 1)) { puts(msg); free(msg); print_stdout_exit(1); } printf("Listening for connections on %s...\n" "Connect from another terminal with \"-connect %s\".\n", get_socket_fname(), this_tty); goto press; } #endif #ifdef INET n = argtonum(arg); if (test_port_number(n)) port = n; if (!mksocket_inet(NULL, port)) print_stdout_exit(1); #endif #if !CURSES && !ALLEGRO return 1; #endif press: press_any_key(); return 1; } static char *getopt_host() { #ifdef INET static char host[84]; const char *s = getopt_str("", "host"); char *p; if (s) { strcpy(host, s); p = strchr(host, ':'); if (!p) strcat(host, ":34034"); return host; } #endif return NULL; } #ifdef INET static void save_host(const char *hostname, int port) { char s[74]; union val v; if (strlen(hostname) < 68) { sprintf(s, "%s:%d", hostname, port); v.p = s; setoption("", "host", v, 2); } } #endif static int connect_to(char *arg, char *p) { #ifndef INET return 0; #else int n = argtonum(p); if (!test_port_number(n)) return 0; if (!*arg) arg = "localhost"; if (mksocket_inet(arg, n)) save_host(arg, n); else print_stdout_exit(1); return 1; #endif } #ifdef TTY_SOCKET static int is_tty_maybe(const char *tty) { #ifndef INET return 1; #else char fname[16] = "/dev/"; struct stat st; if (tty[0] == '/') return 1; if (strlen(tty) > 10) return 0; strcat(fname, tty); return stat(fname, &st) == 0; #endif } #endif static int cmd_connect(const char *name, char *arg) { char *p; if (!arg) arg = getopt_host(); requires_arg(name, arg, "Try -help for more information."); p = strrchr(arg, ':'); if (p) { *p = '\0'; p++; } else if (argtonum(arg) < 0) { #ifdef TTY_SOCKET if (is_tty_maybe(arg)) { connect_tty(arg); return 1; } #endif ; } #ifdef INET else if (!strchr(arg, '.')) { p = arg; arg = ""; } if (!connect_to(arg, p)) { printf("You need to specify a valid port number (%s:PORT).\n" "34034 is a good choice.\n", arg); print_stdout_exit(1); } #else invalid_arg("connect", "Expected tty."); #endif return 1; } static int cmd_name(const char *name, char *arg) { union val v; requires_arg(name, arg, ""); v.p = arg; setoption("", "name", v, 2); return 1; } #endif /* SOCKET */ static int cmd_bg(const char *name, char *arg) { union val v; requires_arg(name, arg, "(black/white)"); v.integ = argtonum(arg); v.integ = v.integ==1 || *arg=='w'; setoption("term", "bg", v, 0); return 1; } static int cmd_color(const char *name, char *arg) { union val v; v.integ = argtonum(arg) != 0; if (*name =='m') v.integ = !v.integ; setoption("term", "color", v, 0); return 1; } static int cmd_ascii(const char *name, char *arg) { union val v; v.integ = argtonum(arg) != 0; if (*name =='v') v.integ = !v.integ; setoption("term", "drawing", v, 0); return 1; } #ifndef NO_BLOCKSTYLES static void unsetbgdot() { if (!getopt_int("term", "bgdot")) unsetoption("term", "bgdot"); } static int cmd_block_bgdot(const char *name, char *arg) { union val v; requires_arg(name, arg, ""); unsetbgdot(); strncpy(v.str, arg, 4); if (v.str[0]==' ') v.str[0] = ' '-1; else if (!v.str[2]) v.str[2] = '_'; if (!strcmp(arg, "0")) v.str[1] = ' '; setoption("term", name, v, 1); return 1; } static int cmd_tt(const char *name, char *arg) { union val v; if (name[2] || argtonum(arg) == 2) { unsetbgdot(); v.integ = -2; } else { v.integ = 0; setoption("term", "bgdot", v, 1); v.integ = -1; } setoption("term", "block", v, 0); return 1; } #endif static void proc_cmdline_opt(const char *name, char *arg) { const struct cmdopt opts[] = { {"[wh]|width|height", cmd_wh}, {"[?h]|help", cmd_help}, #ifdef ALLEGRO {"fullscreen", cmd_fullscreen}, #endif {"nomenu", cmd_nomenu}, {"hiscores|hiscore", cmd_hiscore}, #ifdef NO_MENU {"inputsetup", cmd_inputsetup}, #endif #if JOYSTICK && !ALLEGRO {"js0|js1", cmd_jsopen}, #endif #ifdef SOCKET {"listen", cmd_listen}, {"connect", cmd_connect}, {"name", cmd_name}, #endif {"bg", cmd_bg}, {"color|mono", cmd_color}, {"ascii|vt100", cmd_ascii}, #ifndef NO_BLOCKSTYLES {"block|bgdot", cmd_block_bgdot}, {"tt|tt-bg", cmd_tt}, #endif {NULL} }; const struct cmdopt *o = opts; if (cmd_game_opt(name, arg)) return; while (o->pattern) { if (namematches(name, o->pattern) && o->func(name, arg)) return; o++; } printf("Unrecognized option \"%s\". ", name); puts("Try -help for more information."); print_stdout_exit(1); } void proc_args(char **args, int n) { int i, c; char *p, *q; for (i = 0; i < n; i++) { p = args[i]; if (*p == '/') p++; else while (*p == '-') p++; if (!strlen(p)) continue; if (q = strchr(p, '=')) { *q = '\0'; q++; } else if (i+1 < n) { c = args[i+1][0]; if (c != '-' && (p > args[i] || !islower(c) || namematches(p, "[?h]|help|connect"))) q = args[i+1]; #ifdef SOCKET if (q && i+2 < n && !strcmp(p, "connect") && connect_to(q, args[i+2])) { i += 2; continue; } #endif } proc_cmdline_opt(p, q); if (q && i+1 < n && q == args[i+1]) i++; } } vitetris-0.58.0/src/config.h000066400000000000000000000000761344123051600156640ustar00rootroot00000000000000#ifndef config_h #define config_h #include "config2.h" #endif vitetris-0.58.0/src/config2.h000066400000000000000000000011521344123051600157420ustar00rootroot00000000000000/* should be included from config.h */ #if defined(WIN32) || defined(__WIN32__) #undef WIN32 #define WIN32 1 #define WIN32_LEAN_AND_MEAN #elif defined(MSDOS) || defined(__MSDOS__) || defined(__PACIFIC__) #undef MSDOS #define MSDOS 1 #else #undef UNIX #define UNIX 1 #endif #if UNIX #define CONFIG_FILENAME ".vitetris" #else #define CONFIG_FILENAME "vitetris.cfg" #endif /* Only used if UNIX */ #ifndef HISCORE_FILENAME #define HISCORE_FILENAME "/var/games/vitetris-hiscores" #endif #if __DJGPP__ || __TURBOC__ #undef HAVE_CONIO_H #undef HAVE_GETTEXTINFO #define HAVE_CONIO_H 1 #define HAVE_GETTEXTINFO 1 #endif vitetris-0.58.0/src/draw/000077500000000000000000000000001344123051600152005ustar00rootroot00000000000000vitetris-0.58.0/src/draw/Makefile000066400000000000000000000011771344123051600166460ustar00rootroot00000000000000include ../src-conf.mk OBJS = draw.o draw_menu.o draw2p.o draw2p_menu.o HEADERS = draw.h internal.h ../textgfx/textgfx.h draw.a: $(OBJS) ar rs draw.a $(OBJS) draw.o: draw.c $(HEADERS) ../game/tetris.h ../hiscore.h \ ../netw/sock.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(DTWOPLAYER) $(DSOCKET) -c draw.c draw_menu.o: draw_menu.c $(HEADERS) ../version.h $(CC) $(CCFLAGS) -c draw_menu.c draw2p.o: draw2p.c $(HEADERS) ../game/tetris.h $(CC) $(CCFLAGS) -I.. -c draw2p.c draw2p_menu.o: draw2p_menu.c $(HEADERS) $(CC) $(CCFLAGS) -c draw2p_menu.c clean: rm -f draw.a $(OBJS) rm -f draw_~4s.o draw2~z2.o .PHONY: clean vitetris-0.58.0/src/draw/draw.c000066400000000000000000000227501344123051600163070ustar00rootroot00000000000000#include #include #include /* sprintf */ #include "../game/tetris.h" #include "draw.h" #include "internal.h" #include "../textgfx/textgfx.h" #include "../hiscore.h" #include "../netw/sock.h" /* opponent_name */ char tetrom_colors[7] = { 1, /* I red */ 7, /* J white */ 5, /* L magenta */ 4, /* O blue */ 2, /* S green */ 3, /* T yellow/brown */ 6 /* Z cyan */ }; void drawbl(int bl, int clr, int x, int y) { int c, i; setblockcolor(clr%10); i = clr<10 || textgfx_flags & (TT_BLOCKS | TT_BLOCKS_BG | BLACK_BRACKETS); c = block_chars[i]; while (bl) { setcurs(x, y); i = 1; do { if (!(bl & i)) movefwd(2); else { putch(block_chars[0]); putch(c); } } while (bl & 16-(i <<= 1)); bl >>= 4; y++; } } void next_xy(int pl, int *x, int *y) { if (_HEIGHT_24L) *x = board_x(pl, 3); else if (TWOPLAYER_MODE) *x = (pl==1) ? -9 : board_x(2, 11); else { *x = 1; *y = 15; return; } *y = 1; } void drawstr(const char *str, int n, int x, int y) { char s[8]; const char *p; int m; while (p = strchr(str, '\\')) { m = p-str; memcpy(s, str, m); s[m] = '\0'; str += m+1; if (isdigit(p[1])) { str++; m = p[1]-'0'; } else m = 1; do { printstr_acs(s, n); setcurs(x, ++y); } while (--m); } printstr_acs(str, n); } void drawboard(int pl) { int x = board_x(pl, 0); int i; if (_HEIGHT_24L) { i = x+5; setwcurs(0, i, 0); if (!_MONOCHROME) { setcolorpair(BOARD_FRAME_COLOR); setattr_bold(); } drawstr("lqNk\\x Nx\\2|_N|", 8, i, 0); setcolorpair(BOARD_FRAME_COLOR); setcurs(x, 3); printstr("_____"); movefwd(10); printstr("_____"); i = 4; } else i = 0; x--; setwcurs(0, x, i); setcolorpair(BOARD_FRAME_COLOR); for (i = 0; i < 20; i++) { putch(VLINE); movefwd(20); putch(VLINE); if (i < 19) newln(x); } if (term_height > 20 && term_height != 24) { newln(x); printstr_acs("m*Nj", 20); } else { setcurs(0, term_height-2); newln(0); } #ifdef TWOPLAYER board_bottom_color[pl-1] = BOARD_FRAME_COLOR; #endif } void drawpanel_labels(const char *first, int x) { const char *s = first; int i; setcolorpair(PANEL_LABEL_COLOR); for (i = 1; i <= 9; i += 4) { setcurs(x, i); putch(' '); printstr(s); putch(' '); s = s==first ? "Level" : "Lines"; } } static void printstat_1p() { setattr_normal(); if (!_WHITE_BG) setattr_bold(); setcurs(1, 2); printlong(" %06ld ", player1.score % 1000000); setcurs(3, 6); printint(" %02d ", player1.level); setcurs(3, 10); printint(" %03d ", player1.lines); } void drawpanel_bordercolor(int clr) { if (_MONOCHROME) setattr_normal(); else setcolorpair(clr | 16); } int draw_vline(int x, int y, int h) { if (is_outside_screen(x+1, 0)) return 0; movefwd(x); while (--h) { putch(VLINE); newln(x); } putch(VLINE); return 1; } static void drawpanel_1p() { int h24 = _HEIGHT_24L; int clr = (player1.level % 6)+1; int i; setwcurs(WIN_PANEL, 0, 0); setblockcolor(clr); printstr_acs("lqNu", 8); for (i = 0; i <= 8; i += 4) drawstr("\\xhNx\\3tqNu", 8, 0, i); if (h24) { setcurs(0, 12); putch(LOWLEFT); drawpanel_labels("Score", 1); } else { setcurs(0, 13); printstr_acs("xhNx", 8); drawpanel_labels("Score", 1); setcurs(2, 13); printstr(" Next "); } printstat_1p(); drawpanel_bordercolor(clr); if (h24) drawstr("\\x\\6x", 6, 9, 12); else { drawstr("\\x Nx\\3mqNu", 8, 0, 13); drawstr("\\x\\x", 0, 9, 17); } i = 0; if (h24) i = 4; setwcurs(0, 0, i); drawpanel_bordercolor(clr); draw_vline(board_x(1, 10)+1, i, 20); } static void hiscoreline() { setcolorpair(RED_FG); putnchars('-', 9); setattr_normal(); } static void print_top_scores() { char s[8]; const struct hiscore *hs = hiscores; int pos = 0; int i = 1; if (term_width < 47 || !hs[0].score) return; setwcurs(WIN_TOP_SCORES, 0, 0); setcolorpair(MAGENTA_FG); printstr("Top Scores"); setattr_normal(); while (hs->score && i <= 5) { newln(0); if (!pos && player1.score > hs->score) { hiscoreline(); pos = 1; continue; } putch(i+'0'); putch('.'); if (hs->score < 1000000) putch(' '); sprintf(s, "%06ld", (long) hs->score); printstr(s); hs++; i++; } if (!pos) { newln(0); if (ishiscore()) hiscoreline(); else cleartoeol(); } refreshwin(WIN_TOP_SCORES); } static void print_tetr_stats() { const char letters[8] = "IJLOSTZ"; int sum = 0; int i; if (term_width < 45) return; setwcurs(WIN_TETROM_STATS, 1, 0); for (i = 0; i < 7; i++) { setblockcolor(tetrom_colors[i]); putch(block_chars[0]); putch(letters[i]); putch(block_chars[1]); setattr_normal(); printint(" %03d", tetr_stats[i]); newln(1); sum += tetr_stats[i]; } printstr(" -----"); newln(0); printint("Sum %04d", sum); refreshwin(WIN_TETROM_STATS); } void drawgamescreen_1p() { drawboard(1); refreshwin(0); if (game_paused) clearboard_paused(); else redrawboard(&player1, 19); drawpanel_1p(); print_top_scores(); print_tetr_stats(); refreshwin(WIN_PANEL); } void print_game_message(int pl, const char *str, int bold) { int x = board_x(pl, 4); int n = strlen(str); if (!(game->player[pl-1].rotationsys & ROT_LEFTHAND)) x--; while (n >= 6) { x--; n -= 2; } setwcurs(0, x, _HEIGHT_24L ? 7 : 3); setattr_normal(); if (bold) setcolorpair(MAGENTA_FG); printstr(str); refreshwin(0); } void print_press_key() { print_game_message(1, "PRESS KEY", 1); #ifdef SOCKET if (game->mode & MODE_NETWORK) print_game_message(2, opponent_name, 0); else #endif if (TWOPLAYER_MODE) print_game_message(2, "PRESS KEY", 1); setcurs_end(); } void drawnext(const struct player *p, const struct tetr *next) { int win = WIN_NEXT+isplayer2(p); int bl; int x; if (TWOPLAYER_MODE && !_HEIGHT_24L && term_width < 76) return; clearwin(win); if (next && (bl = next->blocks)) { x = (bl!=TETR_I && bl!=TETR_O); while (!(bl & 15)) bl >>= 4; setcurs(x, 0); drawbl(bl, next->color+10, x, 0); } upd_screen(win); } static void drawboard_bg(const struct player *p, int col) { int lefthand = p->rotationsys & ROT_LEFTHAND; putch( (lefthand && col%2) ? bgdot : ' '); putch(!(lefthand || col%2) ? bgdot : ' '); } void drawblocks(const struct player *p, int bl, int x, int y, enum drawmode mode) { int i, j; x *= 2; while (y < 0) { bl >>= 4; y++; } setwcurs(1+isplayer2(p), x, y); if (mode != CLEAR_BLOCKS) { i = p->piece.color; if (mode == DRAW_PIECE) i += 10; drawbl(bl, i, x, y); } else { setblockcolor(0); while (1) { i = 1; j = x/2; do { if (bl & i) drawboard_bg(p, j); else movefwd(2); j++; } while (bl & 16-(i <<= 1)); if (!(bl >>= 4)) break; y++; setcurs(x, y); } } } void drawrow(const struct player *p, int y) { uint_least32_t bl = p->board[y]; int clr = -1; int i = 0; setwcurs(1+isplayer2(p), 0, y); do { if (clr != (bl & 7)) { clr = bl & 7; setblockcolor(clr); } if (clr) { putch(block_chars[0]); putch(block_chars[1]); } else drawboard_bg(p, i); bl >>= 3; } while (++i < 10); } void redrawboard(const struct player *plr, int y) { while (y >= 0) { drawrow(plr, y); y--; } if (plr->piece.blocks) drawpiece(plr, plr->piece.blocks, plr->piece.x, plr->piece.y); refreshwin(1+isplayer2(plr)); } void clearboard_paused() { int x, y; int i, j; getwin_xy(1, &x, &y); setwcurs(0, x, y); setblockcolor(0); for (i = 0; i < 20; i++) { setcurs(x, y+i); for (j = 0; j < 10; j++) drawboard_bg(&player1, j); } print_game_message(1, "-- PAUSE --", 1); } void upd_stat(const struct player *p, int levelup) { setwcurs(WIN_PANEL, 1, 2); if (TWOPLAYER_MODE) printstat_2p(p); else { if (levelup) drawpanel_1p(); else printstat_1p(); print_top_scores(); print_tetr_stats(); } refreshwin(WIN_PANEL); } static void upddropmark(int pl, int a, int b, int c, int d) { #ifdef TWOPLAYER int clr = board_bottom_color[pl-1]; #else int clr = BOARD_FRAME_COLOR; #endif if (term_height==20 || term_height==24 || pl==2 && game->mode & MODE_NETWORK) return; if (game_running) refreshwin(pl); setwcurs(0, board_x(pl, a), _HEIGHT_24L ? 24 : 20); setcolorpair(clr); putnchars('*', 2*(b-a)); setattr_normal(); putnchars('=', 2*c); setcolorpair(clr); putnchars('*', 2*d); } void upd_dropmarker(const struct player *p, int mv) { int pl = 1+isplayer2(p); int blocks = p->piece.blocks; int col = p->piece.x + !(blocks & 0x1111); int w = 2; switch (blocks) { case 0: col=0; w=0; break; case TETR_I: w = 4; break; case TETR_I2: w = 1; break; default: w += blocks & 0x1111 && blocks & 0x4444; } switch (mv) { case -1: upddropmark(pl, col-1, col-1, w, 1); break; case 0: upddropmark(pl, 0, col, w, 10-col-w); break; case 1: upddropmark(pl, col, col+1, w, 0); } } void hide_dropmarker(const struct player *p) { int i = isplayer2(p); #ifdef TWOPLAYER board_bottom_color[i] = BOARD_FRAME_COLOR; #endif setattr_normal(); upddropmark(i+1, 0, 10, 0, 0); } void drawbox(int x, int y, int w, int h, const char *title) { int i; setcurs(x, y); if (!title) printstr_acs("lqNk", w-2); else { setattr_normal(); setattr_standout(); i = w-strlen(title)-4; printstr_acs("lqN ", i/2); printstr(title); printstr_acs(" qNk", i-i/2); setattr_normal(); } for (i = 2; i < h; i++) { newln(x); printstr_acs("x Nx", w-2); } newln(x); printstr_acs("mqNj", w-2); } void clearbox(int x, int y, int w, int h) { setattr_normal(); setcurs(x, y); while (1) { if (!w) cleartoeol(); else putnchars(' ', w); h--; if (!h) break; newln(x); } } void upd_screen(int i) { refreshwin(i); setcurs_end(); } vitetris-0.58.0/src/draw/draw.h000066400000000000000000000027641344123051600163170ustar00rootroot00000000000000extern char tetrom_colors[7]; void draw_tetris_logo(int x, int y); void print_vitetris_ver(int x, int y); #ifdef TWOPLAYER int board_x(int pl, int col); #else #define board_x(pl, col) (2*col+11) #endif void next_xy(int pl, int *x, int *y); void drawgamescreen_1p(); void drawgamescreen_2p(); void print_game_message(int pl, const char *str, int bold); void print_press_key(); /* tetris.h should be included before */ #ifdef tetris_h void drawnext(const struct player *p, const struct tetr *next); enum drawmode { DRAW_PIECE, DRAW_BLOCKS, CLEAR_BLOCKS }; /* x and y here means column and row in the player's playfield */ void drawblocks(const struct player *p, int bl, int x, int y, enum drawmode mode); #define drawpiece(plr, bl, x, y) drawblocks(plr, bl, x, y, DRAW_PIECE) #define clearblocks(plr, bl, x, y) drawblocks(plr, bl, x, y, CLEAR_BLOCKS) void drawrow(const struct player *p, int y); /* redraw row y and all rows above */ void redrawboard(const struct player *p, int y); void clearboard_paused(); void upd_stat(const struct player *p, int levelup); void upd_garbagemeter(const struct player *p, int n); void show_winner(const struct player *p); void upd_dropmarker(const struct player *p, int mv); void hide_dropmarker(const struct player *p); #define show_dropmarker(p) upd_dropmarker(p, 0) #endif /* tetris_h */ void drawbox(int x, int y, int w, int h, const char *title); void clearbox(int x, int y, int w, int h); void draw_2p_menu_decor(int pl, int x, int y); void upd_screen(int win); vitetris-0.58.0/src/draw/draw2p.c000066400000000000000000000045711344123051600165520ustar00rootroot00000000000000#undef TWOPLAYER #define TWOPLAYER 1 #include "../game/tetris.h" #include "draw.h" #include "internal.h" #include "../textgfx/textgfx.h" char board_bottom_color[2] = {BOARD_FRAME_COLOR, BOARD_FRAME_COLOR}; int board_x(int pl, int col) { int x = 2*col; if (pl == 2) return x+35; if (TWOPLAYER_MODE) return x+1; return x+11; } static void drawboard_frame_2p() { int x = board_x(2, 10)+1; int y = _HEIGHT_24L ? 4 : 0; setwcurs(0, 0, y); if (!_MONOCHROME) { setcolorpair(BOARD_FRAME_COLOR); setattr_bold(); } if (draw_vline(x, y, 20)) { x = board_x(1, 0)-2; setcurs(x, y); drawstr("x\\9x\\9x\\x", 0, x, y); } } void printstat_2p(const struct player *p) { int x; setattr_normal(); if (!_WHITE_BG) setattr_bold(); x = isplayer2(p) ? 7 : 2; setcurs(x, 2); printint(" %d ", p->score); if (x == 2) x--; setcurs(x, 6); printint(" %02d ", p->level); setcurs(x, 10); printint(" %02d ", p->lines); } static void drawpanel_2p() { int i; setwcurs(WIN_PANEL, 0, 0); setblockcolor(4); printstr_acs("tqNu", 10); for (i = 0; i <= 8; i += 4) drawstr("\\xhNx\\3tqNu", 10, 0, i); drawpanel_labels("Wins", 3); printstat_2p(&player1); printstat_2p(&player2); drawpanel_bordercolor(4); drawstr("\\x Nx\\6x Nx", 10, 0, 12); } void drawgamescreen_2p() { drawboard(1); drawboard(2); drawboard_frame_2p(); refreshwin(0); redrawboard(&player1, 19); redrawboard(&player2, 19); drawpanel_2p(); refreshwin(WIN_PANEL); } static void drawredmeter(int x, int n) { int i = 7; int c = ' '; while (i) { if (i <= n) { c = UPARROW; setblockcolor(1); n = 0; } newln(x); putch(c); putch(c); i--; } setattr_normal(); } void upd_garbagemeter(const struct player *p, int n) { char digits[3] = " "; int x = isplayer2(p) ? 9 : 1; if (n) { board_bottom_color[isplayer2(p)] = 17; upd_dropmarker(p, 0); digits[0] = '0'+ n/10; digits[1] = '0'+ n; } setwcurs(WIN_PANEL, 0, 12); drawredmeter(x, n); if (n > 6) n = 6; setcurs(x, 19-n); printstr(digits); refreshwin(WIN_PANEL); } void show_winner(const struct player *p) { int i = 1; while (1) { setwcurs(i, 4, 2); setattr_normal(); setcolorpair(MAGENTA_FG); drawbox(4, 2, 12, 3, (char *)0); setcurs(6, 3); if (!p) printstr(" DRAW "); else { printstr("YOU "); printstr(p==game->player+(i==2) ? "WIN!" : "LOSE"); } refreshwin(i); if (i == 2) break; i = 2; } setcurs_end(); } vitetris-0.58.0/src/draw/draw2p_menu.c000066400000000000000000000003521344123051600175670ustar00rootroot00000000000000#include "draw.h" #include "internal.h" #include "../textgfx/textgfx.h" void draw_2p_menu_decor(int pl, int x, int y) { x++; drawstr("\\l\\x", 0, x, y-1); y += 2; setcurs(x-1, y); putch(pl+'0'); drawstr("P\\x\\2m", 0, x, y); } vitetris-0.58.0/src/draw/draw_menu.c000066400000000000000000000010231344123051600173210ustar00rootroot00000000000000#include "draw.h" #include "internal.h" #include "../textgfx/textgfx.h" #include "../version.h" void draw_tetris_logo(int x, int y) { int bl; drawbl(0x227, 1, x, y); drawbl(0x313, 4, x+7, y); drawbl(1, 4, x+8, y+1); drawbl(0x227, 6, x+12, y); drawbl(0x113, 7, x+19, y); drawbl(0x111, 2, x+24, y); bl = 0x326; if (is_outside_screen(x+33, 0)) bl = 0x322; drawbl(bl, 3, x+27, y); setattr_normal(); } void print_vitetris_ver(int x, int y) { setcurs(x, y); setattr_bold(); printstr(VITETRIS_VER); setattr_normal(); } vitetris-0.58.0/src/draw/internal.h000066400000000000000000000005711344123051600171700ustar00rootroot00000000000000extern char board_bottom_color[2]; void drawbl(int bl, int clr, int x, int y); void drawstr(const char *str, int n, int x, int y); void drawboard(int pl); void drawpanel_labels(const char *first, int x); void drawpanel_bordercolor(int clr); int draw_vline(int x, int y, int h); #ifdef TWOPLAYER void printstat_2p(const struct player *p); #else #define printstat_2p(p) #endif vitetris-0.58.0/src/focus.c000066400000000000000000000017371344123051600155360ustar00rootroot00000000000000#include "focus.h" #if ALLEGRO #include "textgfx/textgfx.h" int in_xterm = 1; int xterm_hasfocus() { if (textgfx_flags & LOST_FOCUS) return 0; return 1; } #elif XLIB #include #include #include int in_xterm = 0; static Display *dpy; static Window xtermwin; void in_xterm_init() { char *s = getenv("WINDOWID"); if (s && sscanf(s, "%lu", &xtermwin)==1 && (dpy = XOpenDisplay(0))) in_xterm = xterm_hasfocus(); } int xterm_hasfocus() { Window w, focusw, root, par, *children; unsigned int n; int i; if (!XGetInputFocus(dpy, &w, &i)) return 0; if (w == xtermwin) return 1; focusw = w; w = xtermwin; while (XQueryTree(dpy, w, &root, &par, &children, &n) && par != root) { if (children) { for (i = 0; i < n; i++) if (children[i] == focusw) { focusw = xtermwin; break; } XFree(children); if (focusw == xtermwin) return 1; } if (par == focusw) return 1; w = par; } return 0; } #endif /* XLIB */ vitetris-0.58.0/src/focus.h000066400000000000000000000001021344123051600155240ustar00rootroot00000000000000extern int in_xterm; void in_xterm_init(); int xterm_hasfocus(); vitetris-0.58.0/src/game/000077500000000000000000000000001344123051600151545ustar00rootroot00000000000000vitetris-0.58.0/src/game/Makefile000066400000000000000000000013311344123051600166120ustar00rootroot00000000000000include ../src-conf.mk OBJS = tetris.o $(tetris2p_obj) game.o wonlost.o HEADERS = tetris.h ../timer.h ../input/input.h ../draw/draw.h game.a: $(OBJS) ar rs game.a $(OBJS) tetris.o: tetris.c $(HEADERS) $(CC) $(CCFLAGS) -I.. -c tetris.c tetris2p.o: tetris2p.c tetris2p.h $(HEADERS) ../netw/sock.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(DSOCKET) -c tetris2p.c game.o: game.c game.h tetris.h tetris2p.h ../options.h ../input/input.h \ ../netw/sock.h ../hiscore.h ../menu/menu.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(DTWOPLAYER) $(DJOYSTICK) $(DSOCKET) $(DNO_MENU) -c game.c wonlost.o: wonlost.c game.h ../options.h $(CC) $(CCFLAGS) -c wonlost.c clean: rm -f game.a tetris.o tetris2p.o game.o wonlost.o .PHONY: clean vitetris-0.58.0/src/game/game.c000066400000000000000000000044711344123051600162370ustar00rootroot00000000000000#include #include #include #include #include "game.h" #include "tetris.h" #include "tetris2p.h" #include "../options.h" #include "../input/input.h" #include "../netw/sock.h" #include "../hiscore.h" #include "../menu/menu.h" extern int in_menu; int testgameopt(const char *key, int val, int pl) { const char *keys[6] = {"mode", "level", "height", "lines","rotate","softdrop"}; const char max[6] = {127, 9, 5, 127, 3, 20}; int i = 0; int n = 6; if (pl) { i++; n--; } for (; i < n; i++) if (!strcmp(key, keys[i])) return val >= 0 && val <= max[i] ? i+1 : -1; return 0; } static void initplayer(struct player *p) { p->startlevel = 0; p->height = 0; p->lineslimit = 25; p->rotationsys = ROT_CLOCKWISE | ROT_LEFTHAND; p->score = 0; } void initgame() { struct player *p = game->player; int pl = 0; struct option *o = getoptions(""); int v; int i; srand(time(NULL)); game->mode = getopt_int("", "mode"); #ifndef TWOPLAYER game->mode &= ~(MODE_2PLAYER | MODE_NETWORK); #else if (socket_fd > -1) game->mode |= MODE_2PLAYER | MODE_NETWORK; #endif game->state = 0; game->next = NULL; initplayer(p); if (!TWOPLAYER_MODE) softdrop_speed = 1; else { initplayer(p+1); pl = 1; if (socket_fd == -1) o = getoptions("player1"); } while (1) { if (!o) { if (!TWOPLAYER_MODE || pl==2 || socket_fd > -1) break; p++; pl = 2; o = getoptions("player2"); continue; } v = o->val.integ; i = testgameopt(opt_key(o), v, pl); if (i>=2 && i<=5) (&p->startlevel)[i-2] = v; else if (i==6) softdrop_speed = v; #ifdef SOCKET else if (!strcmp(opt_key(o), "name")) { if (opt_isint(o)) sprintf(my_name, "%d", v); else strncpy(my_name, opt_longstr(o), 16); } #endif o = o->next; } #ifdef SOCKET if (socket_fd > -1) { # ifndef NO_MENU if (in_menu) request_playerlist(); # endif sock_initgame(); } else #endif #if TWOPLAYER && JOYSTICK if (TWOPLAYER_MODE) initplayerinput() #endif ; } int startgame() { setupplayer(&player1); if (TWOPLAYER_MODE) { setupplayer(&player2); #ifdef SOCKET if (socket_fd < 0) #endif game->mode &= ~MODE_NETWORK; if (!startgame_2p()) return 0; #ifdef NO_MENU return 1; #else return 0; #endif } if (!hiscores[0].score) readhiscores(NULL); return startgame_1p() && gameovermenu(); } vitetris-0.58.0/src/game/game.h000066400000000000000000000007671344123051600162500ustar00rootroot00000000000000/* returns 0 if key is unrecognized, -1 if val is invalid */ int testgameopt(const char *key, int val, int pl); #ifndef TWOPLAYER #define allocgame(twop) struct game_1p gm1p; game = (struct game *) &gm1p #else #define allocgame(twop) struct game_2p gm2p; game = (struct game *) &gm2p #endif void initgame(); /* returns 1 to play again */ int startgame(); const char *get_wonlost_stats(const char *me, const char *opponent); void upd_wonlost_stats(const char *me, const char *opponent, int won); vitetris-0.58.0/src/game/tetris.c000066400000000000000000000401721344123051600166360ustar00rootroot00000000000000#include #include #include "tetris.h" #include "../timer.h" #include "../input/input.h" #include "../draw/draw.h" struct game *game = NULL; char clearedlines[4]; #define RETURN_ON_INPUT 4 /* process single-player input */ static int processinput(int tm, int flags); int randnum(int n) { return (int) (n*(rand()/(RAND_MAX+1.0))); } void gettetrom(struct tetr *t, int i) { t->x = 3; t->y = -3; switch (i) { case 0: t->y = -4; t->blocks = TETR_I; break; case 1: t->blocks = TETR_J; break; case 2: t->blocks = TETR_L; break; case 3: t->y = -2; t->blocks = TETR_O; break; case 4: t->blocks = TETR_S; break; case 5: t->blocks = TETR_T; break; case 6: t->blocks = TETR_Z; break; default: t->blocks = 0; return; } t->color = tetrom_colors[i]; } int hitbtm(struct tetr *p, struct player *plr) { uint_least32_t *board; int i, mask; int x, y; i = 12; while (!(p->blocks >> i)) i -= 4; if ((y = p->y+i/4) == 19) return 1; board = plr->board; if (y < -1 || !board[y+1]) return 0; mask = 15; while (1) { if (p->blocks & mask<blocks & 1<>3*(p->x+x) & 7) return 1; mask ^= p->blocks>>i & mask; } if (!i || y < 0) break; i -= 4; y--; } return 0; } static void levelup(struct player *p) { p->level++; if (!p->level) p->falltime = 799; else if (p->level < 9) p->falltime -= 83; else if (p->level == 9) p->falltime = 100; else if (p->level == 10) p->falltime = 83; else if (p->level < 20) p->falltime -= 5 + p->level%2; else if (p->level < 30) p->falltime -= 2; } static void upd_score_level(struct player *p, int n) { int lines; if (!(game->mode & MODE_2PLAYER)) { switch (n) { case 1: p->score += 40*(p->level+1); break; case 2: p->score += 100*(p->level+1); break; case 3: p->score += 300*(p->level+1); break; case 4: p->score += 1200*(p->level+1); } } if (game->mode & MODE_BTYPE) { p->lines -= n; lines = p->lineslimit - p->lines; if (p->lines <= 0) { p->lines = 0; p->piece.y = -1; } } else { p->lines += n; lines = p->lines; } if (p->level == p->startlevel) { if (lines >= 10*p->startlevel+10 || lines >= 100) levelup(p); } else if (lines/10 != (lines-n)/10) levelup(p); } static void clearlines(struct player *p, int n) { uint_least32_t *board = p->board; unsigned char lines[4]; int i; upd_score_level(p, n); memcpy(lines, clearedlines, 4); for (i = 0; i < n; i++) board[lines[i]-1] = 0; while (n--) { for (i = lines[n]-1; i > 0; i--) { board[i] = board[i-1]; if (!n && !board[i]) break; } if (board[0]) board[0] = 0; for (i = n-1; i >= 0; i--) lines[i]++; } } static void draw_lineclear_anim(int n) { int x, i; int t = gettm(0); int tm; for (x = 4; x >= 0; x--) { for (i = 0; i < n; i++) { clearblocks(&player1, 1, x, clearedlines[i]-1); clearblocks(&player1, 1, 9-x, clearedlines[i]-1); } tm = CLEAR_DELAY/5; tm = (5-x)*tm-gettm(t)+t; processinput(tm, DISCARD_MOVES | NO_PAUSE); } redrawboard(&player1, clearedlines[n-1]-1); } static int lockdelay() { struct tetr *p = &player1.piece; int t = gettm(0); int d = 0; int x1, x2; int b1, b2; x1 = x2 = p->x; b1 = b2 = p->blocks; while (d < LOCK_DELAY) { switch (processinput(LOCK_DELAY-d, RETURN_ON_INPUT)) { case -2: return -2; case 0: return 0; } if (!hitbtm(p, &player1)) return 1; if (p->x != x2) { if (p->x == x1) break; x1 = x2; x2 = p->x; } else if (p->blocks != b2) { if (p->blocks == b1) break; b2 = p->blocks; } else d = -1; if (d == -1) d = gettm(t)-t; else { d = gettm(t)-t-LOCK_DELAY+d; if (d < 0) d = 0; else if (d > LOCK_DELAY-10) d = LOCK_DELAY-10; t = gettm(0)-d; } } return 0; } void lockpiece(struct player *plr) { struct tetr *p = &plr->piece; int x, y; int n = 0; if (!p->blocks) return; drawblocks(plr, p->blocks, p->x, p->y, DRAW_BLOCKS); hide_dropmarker(plr); while (!(p->blocks & 15)) { p->blocks >>= 4; p->y++; } if (p->y < 0) { p->blocks = 0; return; } memset(clearedlines, 0, 4); y = p->y; do { x = 0; while (!(p->blocks & 1<board[y] |= (uint_least32_t) p->color << 3*(p->x+x); while (p->blocks & 1<<++x); for (x = 0; x < 10; x++) if (!(plr->board[y]>>3*x & 7)) break; if (x == 10) clearedlines[n++] = y+1; y++; } while (p->blocks >>= 4); x = plr->level; if (n) clearlines(plr, n); upd_stat(plr, x != plr->level); if (n && !(game->mode & MODE_2PLAYER)) draw_lineclear_anim(n); } static int can_moveright(struct tetr *p, uint_least32_t *board) { int bl = p->blocks; int i; int x, y; if (i = (bl != TETR_I)) i += !(bl & 0x444); if (p->x-i > 5) return 0; y = p->y; while (y < 0 || !(bl & 15)) { bl >>= 4; y++; } x = 3-i; i = 0; while (1) { while (!(bl & 1<>3*(p->x+x+1) & 7) return 0; if (x) bl &= ~(((1<> (i += 4))) break; x = 2-!(bl & 0x444); y++; } return bl; } void moveright(struct player *plr) { struct tetr *p = &plr->piece; int bl = can_moveright(p, plr->board); int y = p->y; int i = 0; if (!bl) { if (plr->falltime < LOCK_DELAY) { plr->mvright_tm = gettm(0); plr->mvleft_tm = 0; } return; } while (y < 0 || !(p->blocks & 15<x+1, y); bl = p->blocks >> i; do { i = 1; while (!(bl & i)) i <<= 1; clearblocks(plr, bl & i, p->x, y); y++; } while (bl >>= 4); upd_dropmarker(plr, 1); p->x++; } static int can_moveleft(struct tetr *p, uint_least32_t *board) { int bl; int i; int x, y; if (!(p->x + !(p->blocks & 0x111))) return 0; bl = p->blocks; y = p->y; while (y < 0 || !(bl & 15)) { bl >>= 4; y++; } i = 0; while (1) { x = 0; while (!(bl & 1<>3*(p->x+x-1) & 7) return 0; if (x < 3) bl &= ~(16-(1<> (i += 4))) break; y++; } return bl; } void moveleft(struct player *plr) { struct tetr *p = &plr->piece; int bl = can_moveleft(p, plr->board); int y = p->y; int i = 0; if (!bl) { if (plr->falltime < LOCK_DELAY) { plr->mvleft_tm = gettm(0); plr->mvright_tm = 0; } return; } while (y < 0 || !(p->blocks & 15<x-1, y); bl = p->blocks >> i; do { i = 8; while (!(bl & i)) i >>= 1; clearblocks(plr, bl & i, p->x, y); y++; } while (bl >>= 4); upd_dropmarker(plr, -1); p->x--; } static void drop_score() { if (!(game->mode & MODE_2PLAYER)) player1.score++; } int movedown(struct player *plr, int drop) { struct tetr *p = &plr->piece; int bl; int i, mask; if (hitbtm(p, plr)) return 0; if (drop) drop_score(); bl = 0; mask = 15; for (i = 12; i >= 0; i -= 4) if (p->blocks & mask<blocks & mask<>i & mask; } drawpiece(plr, bl, p->x, p->y+1); bl = 0; mask = 15; for (i = 0; i <= 12; i += 4) if (p->blocks & mask<blocks & mask<>i & mask; } clearblocks(plr, bl, p->x, p->y); p->y++; if (plr->falltime >= LOCK_DELAY) goto out; if (!drop && p->y >= 0) { if (plr->mvright_tm && LOCK_DELAY - plr->falltime >= gettm(plr->mvright_tm) - plr->mvright_tm) moveright(plr); else if (plr->mvleft_tm && LOCK_DELAY - plr->falltime >= gettm(plr->mvleft_tm) - plr->mvleft_tm) moveleft(plr); } plr->mvright_tm = 0; plr->mvleft_tm = 0; out: upd_screen(1+(plr > game->player)); return 1; } static int can_rotate(int bl, int x, int y, uint_least32_t *board) { int row; int i = bl != TETR_I; if (i) i += !(bl & 0x444); if (x-i > 6) return 0; if (x + !(bl & 0x111) < 0) return 0; while (y < 0 || !(bl & 15)) { bl >>= 4; y++; } x *= 3; while (bl) { if (y > 19) return 0; row = board[y]>>x & 0xFFF; i = 1; while (row) { if (bl & i && row & 7) return 0; row >>= 3; i <<= 1; } bl >>= 4; y++; } return 1; } static void rotate_JL(struct player *plr, int bl) { struct tetr *p = &plr->piece; int x = p->x; int y = p->y; if (can_rotate(bl, x, y, plr->board)) { drawpiece(plr, bl, x, y); clearblocks(plr, p->blocks ^ 0x20, x, y); p->blocks = bl; } } void rotate(struct player *plr, int clockwise) { struct tetr *p = &plr->piece; uint_least32_t *board = plr->board; int y = p->y; int i = !(plr->rotationsys & ROT_LEFTHAND); switch (p->blocks) { case TETR_I: if (!can_rotate(TETR_I2, p->x+i, y, board)) return; p->x += i; p->blocks = TETR_I2; drawpiece(plr, 0x1011, p->x+1, y); clearblocks(plr, i?11:13, p->x-i, y+2); break; case TETR_I2: if (!can_rotate(TETR_I, p->x-i, y, board)) return; p->x -= i; p->blocks = TETR_I; drawpiece(plr, 15, p->x, y+2); clearblocks(plr, 0x1011, p->x+i+1, y); break; case TETR_J3: clockwise = !clockwise; case TETR_J: rotate_JL(plr, clockwise ? TETR_J2 : TETR_J4); break; case TETR_J4: clockwise = !clockwise; case TETR_J2: rotate_JL(plr, clockwise ? TETR_J3 : TETR_J); break; case TETR_L3: clockwise = !clockwise; case TETR_L: rotate_JL(plr, clockwise ? TETR_L2 : TETR_L4); break; case TETR_L4: clockwise = !clockwise; case TETR_L2: rotate_JL(plr, clockwise ? TETR_L3 : TETR_L); break; case TETR_S: if (!can_rotate(TETR_S2, p->x+i, y, board)) return; p->blocks = TETR_S2; if (!i) { drawpiece(plr, 0x11, p->x, y); clearblocks(plr, 0x14, p->x, y+1); } else { p->x++; drawpiece(plr, 0x201, p->x, y); clearblocks(plr, 3, p->x-1, y+2); } break; case TETR_S2: if (!can_rotate(TETR_S, p->x-i, y, board)) return; p->blocks = TETR_S; if (!i) { drawpiece(plr, 0x14, p->x, y+1); clearblocks(plr, 0x11, p->x, y); } else { p->x--; drawpiece(plr, 3, p->x, y+2); clearblocks(plr, 0x201, p->x+1, y); } break; case TETR_T: i = clockwise ? TETR_T2 : TETR_T4; if (!can_rotate(i, p->x, y, board)) return; p->blocks = i; drawpiece(plr, 1, p->x+1, y); clearblocks(plr, 1, p->x+(clockwise?2:0), y+1); break; case TETR_T2: i = clockwise ? TETR_T3 : TETR_T; if (!can_rotate(i, p->x, y, board)) return; p->blocks = i; drawpiece(plr, 1, p->x+2, y+1); clearblocks(plr, 1, p->x+1, y+(clockwise?2:0)); break; case TETR_T3: i = clockwise ? TETR_T4 : TETR_T2; if (!can_rotate(i, p->x, y, board)) return; p->blocks = i; drawpiece(plr, 1, p->x+1, y+2); clearblocks(plr, 1, p->x+(clockwise?0:2), y+1); break; case TETR_T4: i = clockwise ? TETR_T : TETR_T3; if (!can_rotate(i, p->x, y, board)) return; p->blocks = i; drawpiece(plr, 1, p->x, y+1); clearblocks(plr, 1, p->x+1, y+(clockwise?0:2)); break; case TETR_Z: if (!can_rotate(TETR_Z2, p->x+i, y, board)) return; p->blocks = TETR_Z2; if (!i) { drawpiece(plr, 0x102, p->x, y); clearblocks(plr, 3, p->x+1, y+2); } else { p->x++; drawpiece(plr, 0x11, p->x+1, y); clearblocks(plr, 0x41, p->x-1, y+1); } break; case TETR_Z2: if (!can_rotate(TETR_Z, p->x-i, y, board)) return; p->blocks = TETR_Z; if (!i) { drawpiece(plr, 3, p->x+1, y+2); clearblocks(plr, 0x102, p->x, y); } else { p->x--; drawpiece(plr, 0x41, p->x, y+1); clearblocks(plr, 0x11, p->x+2, y); } } upd_dropmarker(plr, 0); } static int atspawnpos(struct tetr *p) { const short bl[7] = {TETR_I,TETR_J,TETR_L,TETR_O,TETR_S,TETR_T,TETR_Z}; struct tetr t; int i; if (p->x != 3 || p->y > 0) return 0; for (i = 0; i < 7; i++) if (p->blocks == bl[i]) { gettetrom(&t, i); return (p->y == t.y+2); } return 0; } static void movedown_n(struct player *plr, int drop, int n) { struct tetr *p = &plr->piece; int bl = p->blocks; int y = p->y; int i, x; for (i = 0; i < n && !hitbtm(p, plr); i++) { p->y++; if (drop) drop_score(); } if (y == p->y) return; drawpiece(plr, p->blocks, p->x, p->y); i = 0; do { if (bl & 15) { x = 0; while (!(bl & 1<= p->y && p->blocks & 1<<4*(i-p->y+y)+x) bl ^= 1 << x; while (bl & 1<<++x); clearblocks(plr, bl & 15, p->x, y+i); } i++; } while (y+i < 19 && (bl >>= 4)); } int harddrop(struct player *plr, int safe) { struct tetr *p = &plr->piece; if (safe && atspawnpos(p)) return -1; movedown_n(plr, 1, 19); drawblocks(plr, p->blocks, p->x, p->y, DRAW_BLOCKS); lockpiece(plr); return 0; } int softdrop(int n, int safe) { struct player *p = &player1; int t = gettm(0); int tm = -1; int y = p->piece.y; if (safe && atspawnpos(&p->piece)) return -1; if (!movedown(p, 1)) return 0; n--; while (n > 0) { y = p->piece.y; movedown_n(p, 1, 1+(n>1)); processinput(tm-gettm(t)+t, DISCARD_DROPS); t = gettm(0); if (tm == -1) { tm = 2*p->falltime/20; if (tm > 10) tm = 10; } if (hitbtm(&p->piece, p)) return 2; n -= p->piece.y-y; } return 1; } static int newclr(int old) { int clr = randnum(7)+1; if (clr == old) return newclr(0); return clr; } static void gen_garbage_height(struct player *p, int h) { int c, clr = randnum(7)+1; int x, i; if (p > game->player && p->height == player1.height) { memcpy(p->board, player1.board, 20*sizeof(uint_least32_t)); return; } switch (h) { case 1: case 2: h = 2*h+1; break; default: h = 2*(h+1); } while (h) { i = 0; for (x = 0; x < 10; x++) { if (!randnum(2)) continue; i++; if (i == 10) break; if (x && !(p->board[20-h]>>3*(x-1) & 7)) { c = p->board[19-h]>>3*x & 7; if (c && c != clr) clr = c; else clr = newclr(clr); } p->board[20-h] |= (uint_least32_t) clr << 3*x; } h--; } } void setupplayer(struct player *p) { p->piece.blocks = 0; p->piece.y = 0; memset(p->board, 0, 20*sizeof(int_least32_t)); if (p->height) gen_garbage_height(p, p->height); if (!(game->mode & MODE_2PLAYER)) { p->score = 0; memset(tetr_stats, 0, 7); } p->level = -1; while (p->level < p->startlevel) levelup(p); p->lines = (game->mode & MODE_BTYPE) ? p->lineslimit : 0; } static int nextpiece(struct tetr *next) { int i = randnum(7); player1.piece = *next; gettetrom(next, i); tetr_stats[i]++; drawnext(&player1, next); return movedown(&player1, 0) && movedown(&player1, 0); } int startgame_1p() { struct tetr next; int i = randnum(7); int t; drawgamescreen_1p(); gettetrom(&next, i); drawnext(&player1, &next); game->next = &next; if (!startgame_wait(SINGLE_PL)) return 0; tetr_stats[i] = 1; upd_stat(&player1, 0); while (nextpiece(&next)) { spawn_discard_drops(0); t = gettm(0); show_dropmarker(&player1); while (1) { t = player1.falltime-gettm(t)+t; i = processinput(t, 0); if (!i) break; if (i == -2) return 0; gravity: t = gettm(0); if (i == 2 || movedown(&player1, 0)) continue; i = lockdelay(); if (i == -2) return 0; if (i) goto gravity; lockpiece(&player1); break; } if (player1.piece.y < 0) break; if (processinput(SPAWN_DELAY, DISCARD_MOVES) == -2) return 0; } game->state = GAME_OVER; return 1; } int startgame_wait(int n) { int key; print_press_key(); game->state = 0; key = getkeypress_block(n); n = processkey_ingame(key, DISCARD_MOVES | NO_PAUSE); if (n == -2) return 0; upd_screen(1); if (game->mode & MODE_2PLAYER) upd_screen(2); game->state = GAME_RUNNING; return 1; } int pausegame() { int t = gettm(0); int key; game->state = GAME_PAUSED; clearboard_paused(); hide_dropmarker(&player1); drawnext(&player1, NULL); do key = getkeypress_block(SINGLE_PL); while (gettm(t)-t < 500); if (processkey_ingame(key, NO_PAUSE | DISCARD_MOVES) == -2) return -2; upd_screen(1); show_dropmarker(&player1); drawnext(&player1, game->next); game->state = GAME_RUNNING; return 2; } static int processinput(int tm, int flags) { int key; int t = gettm(0); int d = 0; int ret; upd_screen(1); while (d < tm) { ret = -1; if (key = getkeypress(tm-d, IN_GAME | SINGLE_PL)) { ret = processkey_ingame(key, flags); if (!ret) { lockpiece(&player1); return 0; } } if (abs(ret) == 2 || ret > -1 && (flags & RETURN_ON_INPUT)) return ret; d = gettm(t)-t; } if (!(flags & (DISCARD_MOVES | NO_PAUSE | RETURN_ON_INPUT))) { tm -= d; d = 0; while (tm <= -player1.falltime) { tm += player1.falltime; d++; } if (d) { movedown_n(&player1, 0, d); upd_screen(1); } } return 1; } vitetris-0.58.0/src/game/tetris.h000066400000000000000000000055051344123051600166440ustar00rootroot00000000000000#ifndef tetris_h #define tetris_h #include "int32t.h" #define TETR_I 0xF00 /* | | # | */ #define TETR_I2 0x2222 /* | | # | */ /* |####| # | | | # | */ #define TETR_J 0x470 /* | | # |# | ## | */ #define TETR_J2 0x322 /* |#x# | x |#x# | x | */ #define TETR_J3 0x71 /* | # |## | | # | */ #define TETR_J4 0x226 #define TETR_L 0x170 /* | |## | # | # | */ #define TETR_L2 0x223 /* |#x# | x |#x# | x | */ #define TETR_L3 0x74 /* |# | # | | ## | */ #define TETR_L4 0x622 #define TETR_O 0x66 /* | ## | */ /* | ## | */ #define TETR_S 0x360 /* | |# | */ #define TETR_S2 0x231 /* | x# |#x | */ /* |## | # | */ #define TETR_T 0x270 /* | | # | # | # | */ #define TETR_T2 0x232 /* |#x# |#x |#x# | x# | */ #define TETR_T3 0x72 /* | # | # | | # | */ #define TETR_T4 0x262 #define TETR_Z 0x630 /* | | # | */ #define TETR_Z2 0x132 /* |#x |#x | */ /* | ## |# | */ #define SPAWN_DELAY 166 #define LOCK_DELAY 166 #define CLEAR_DELAY 332 struct tetr { short blocks; signed char x, y; char color; }; /* rotation sys flags */ #define ROT_CLOCKWISE 1 #define ROT_LEFTHAND 2 struct player { char startlevel; char height; char lineslimit; char rotationsys; struct tetr piece; uint_least32_t board[20]; int_least32_t score; signed char level; short falltime; short lines; short mvleft_tm; short mvright_tm; }; /* game modes */ #define MODE_1PLAYER 1 #define MODE_2PLAYER 2 #define MODE_BTYPE 4 #define MODE_NETWORK 8 /* game states */ #define GAME_RUNNING 1 #define GAME_PAUSED 2 #define GAME_OVER 4 #define GAME_members(n) \ char mode; \ char state; \ struct tetr *next; \ struct player player[n] \ extern struct game { GAME_members(1); } *game; struct game_1p { GAME_members(1); unsigned char data[8]; }; struct game_2p { GAME_members(2); }; #define game_running (game->state & GAME_RUNNING) #define game_paused (game->state & GAME_PAUSED) #define game_over (game->state & GAME_OVER) #define player1 game->player[0] #define player2 game->player[1] #define tetr_stats ((struct game_1p *) game)->data #define softdrop_speed ((struct game_1p *) game)->data[7] extern char clearedlines[4]; int randnum(int n); void gettetrom(struct tetr *t, int i); int hitbtm(struct tetr *piece, struct player *p); void lockpiece(struct player *p); void moveright(struct player *p); void moveleft(struct player *p); int movedown(struct player *p, int drop); void rotate(struct player *p, int clockwise); int harddrop(struct player *p, int safe); int softdrop(int n, int safe); void setupplayer(struct player *p); int startgame_1p(); int startgame_wait(int flags); int pausegame(); #ifdef TWOPLAYER #define TWOPLAYER_MODE (game->mode & MODE_2PLAYER) #define isplayer2(p) ((p) > game->player) #else #define TWOPLAYER_MODE 0 #define isplayer2(p) 0 #endif #endif /* !tetris_h */ vitetris-0.58.0/src/game/tetris2p.c000066400000000000000000000277311344123051600171060ustar00rootroot00000000000000#include #include #undef TWOPLAYER #define TWOPLAYER 1 #include "tetris.h" #include "tetris2p.h" #include "game.h" /* wonlost stats */ #include "../timer.h" #include "../input/input.h" #include "../draw/draw.h" #ifndef SOCKET #define SOCKET_EMPTY_DEFS 1 #endif #include "../netw/sock.h" struct tetris2p tetris2p[2]; struct player *winner = NULL; char *tetrom_seq = NULL; static int tetrom_seq_len = -1; static int tetrom_seq_pos[2]; #ifdef SOCKET static int pl2_has_next; #endif static void free_tetrom_seq() { if (tetrom_seq) { free(tetrom_seq); tetrom_seq = NULL; tetrom_seq_len = 0; tetrom_seq_pos[0] = 0; tetrom_seq_pos[1] = 0; } } static void gen_tetrom_seq(int i, int n) { n += i; if (n > tetrom_seq_len) { tetrom_seq = !tetrom_seq ? malloc(n) : realloc(tetrom_seq, n); if (tetrom_seq_len == -1) atexit(free_tetrom_seq); tetrom_seq_len = n; } for (; i < n; i++) tetrom_seq[i] = randnum(7); } static int draw_lineclear_step(struct player *plr, struct tetris2p *tet, int first) { char *lines = tet->clearedlines; int n, x; n = strlen(lines); if (first) tet->x1 = 6; x = --tet->x1; if (x) { while (n) { n--; clearblocks(plr, 1, x-1, lines[n]-1); clearblocks(plr, 1, 10-x, lines[n]-1); } upd_screen(1+(tet>tetris2p)); tet->delay = CLEAR_DELAY/5; } else { redrawboard(plr, lines[n-1]-1); memset(lines, 0, 4); } return x; } static void sendgarbage(struct tetris2p *tet) { int n = strlen(tet->clearedlines); int i; if (n < 4) n--; if (n > 0) { i = tet==tetris2p; tetris2p[i].garbage[0] += n; if (tetris2p[i].garbage[0] > 12) tetris2p[i].garbage[0] = 12; upd_garbagemeter(game->player+i, tetris2p[i].garbage[0]); } } static void getgarbage_row(struct player *plr, char *garbg) { int i, clr; uint_least32_t bl; if (!garbg[1] || garbg[2] == 8) { do i = randnum(10)+1; while (i == garbg[1]); garbg[1] = i; garbg[2] = 0; } garbg[2]++; bl = plr->board[18]; if (!bl) clr = 1; else { while (!(bl & 7)) bl >>= 3; clr = (bl & 7); } for (i = 0; i < 10; i++) if (i+1 != garbg[1]) plr->board[19] |= clr << 3*i; } static void getgarbage(struct player *plr, char *garbg) { int i; if (!garbg[0]) return; if (NETPLAY && plr == &player1) sock_sendgarbage_num(garbg[0]+12); while (garbg[0] && !plr->board[0]) { for (i = 0; i < 19; i++) plr->board[i] = plr->board[i+1]; plr->board[19] = 0; if (!NETPLAY || plr == &player1) getgarbage_row(plr, garbg); redrawboard(plr, 19); garbg[0]--; } hide_dropmarker(plr); upd_garbagemeter(plr, garbg[0]); if (garbg[0]) plr->piece.y = -1; } static void spawndelay(struct player *plr, struct tetris2p *tet) { tet->falltm = plr->falltime; tet->delay = SPAWN_DELAY; if (!NETPLAY || tet==tetris2p) getgarbage(plr, tet->garbage); #ifdef SOCKET else if (sock_flags & PL2_GARBAGE) getgarbage_player2(); #endif } #ifdef SOCKET static void fix_delayed_garbage(int n) { struct tetr *p = &player2.piece; p->y -= n; while (n && !hitbtm(p, &player2)) { p->y++; n--; } if (n) { redrawboard(&player2, 19); n = p->y; if (p->blocks == TETR_I) n += 2; else if (!(p->blocks & 7)) n++; if (n < 0) /* game over */ tetris2p[1].delay = 1; } } void getgarbage_player2() { char *garbg = tetris2p[1].garbage; int n = garbg[1]; sock_sendgarbage_num(n); garbg[0] -= n; getgarbage(&player2, garbg+1); if (!garbg[1]) { if (garbg[0] > 0) upd_garbagemeter(&player2, garbg[0]); if (!tetris2p[1].delay) fix_delayed_garbage(n); } sock_flags &= ~PL2_GARBAGE; } static void sendnext(struct player *p) { int i; if (is_server) { if (i = isplayer2(p)) { if (pl2_has_next) return; pl2_has_next = 1; } i = tetrom_seq_pos[i]+1; if (i >= tetrom_seq_len) gen_tetrom_seq(i, 1); sock_sendnext(p, tetrom_seq[i]); } } #else #define sendnext(p) #endif static void lockdelay(struct player *plr, struct tetris2p *tet) { struct tetr *p = &plr->piece; tet->falltm = 0; tet->delay = LOCK_DELAY; tet->x1 = p->x; tet->x2 = p->x; tet->b1 = p->blocks; tet->b2 = p->blocks; if (NETPLAY) sendnext(plr); } static int upd_lockdelay_state(struct player *plr, struct tetris2p *tet) { struct tetr *p = &plr->piece; if (!hitbtm(p, plr)) { tet->delay = 0; tet->falltm = plr->falltime; tet->b1 = 0; movedown(plr, 0); return 1; } if (NETPLAY && tet>tetris2p) { tet->delay = LOCK_DELAY; return 1; } if (tet->delay <= 0) return 0; if (p->x != tet->x2) { if (p->x == tet->x1) return 0; tet->delay = LOCK_DELAY; tet->x1 = tet->x2; tet->x2 = p->x; } else if (p->blocks != tet->b2) { if (p->blocks == tet->b1) return 0; tet->delay = LOCK_DELAY; tet->b2 = p->blocks; } return 1; } static void lockpiece_2p(struct player *plr, struct tetris2p *tet) { if (NETPLAY) { if (tet>tetris2p && plr->piece.blocks) { lockdelay(plr, tet); return; } if (!tet->b1) sendnext(plr); if (plr->piece.blocks) { sock_sendpiece(plr); sock_sendbyte(HARDDROP); } } lockpiece(plr); if (!clearedlines[0]) { upd_screen(1+(tet>tetris2p)); spawndelay(plr, tet); } else { tet->falltm = 0; memcpy(tet->clearedlines, clearedlines, 4); draw_lineclear_step(plr, tet, 1); sendgarbage(tet); } tet->b1 = 0; } static void show_next(struct player *p, int i) { struct tetr next; gettetrom(&next, i); drawnext(p, &next); } int nextpiece_2p(struct player *plr) { struct tetris2p *tet = tetris2p; int *i = tetrom_seq_pos; int *j = tetrom_seq_pos; char *p; if (plr->piece.y < 0) return 0; if (plr == &player1) { j++; spawn_discard_drops(1); } else { i++; tet = tetris2p+1; spawn_discard_drops(2); #ifdef SOCKET pl2_has_next = 0; #endif } if (*i+1 >= tetrom_seq_len) { memmove(tetrom_seq, tetrom_seq+*j, *i-*j+1); *i -= *j; *j = 0; gen_tetrom_seq(*i+1, 8); } p = tetrom_seq+*i; if (!NETPLAY || is_server) *i += 1; #ifdef SOCKET else if (*p==0x7F) { sock_flags &= ~PL2_IN_GAME; return 0; } #endif gettetrom(&plr->piece, *p); #ifdef SOCKET if (p[1]==0x7F) drawnext(plr, NULL); else #endif show_next(plr, p[1]); if (NETPLAY && !is_server) { *p = p[1]; p[1] = 0x7F; } tet->falltm = plr->falltime; tet->delay = 0; if (movedown(plr, 0) && movedown(plr, 0)) { show_dropmarker(plr); upd_screen(0); return 1; } return 0; } static int getwaittm() { int tm = (tetris2p[0].delay) ? tetris2p[0].delay : tetris2p[0].falltm; if (tetris2p[1].delay) { if (tm > tetris2p[1].delay) tm = tetris2p[1].delay; } else if (tm > tetris2p[1].falltm) tm = tetris2p[1].falltm; #ifdef SOCKET if (tm > 1000) tm = 1000; #endif return tm; } static int processkey(int *pl2) { struct tetris2p *tet = tetris2p; int key = getkeypress(getwaittm(), IN_GAME); int flags; *pl2 = 0; if (!key) return -1; if (key & PLAYER_2) { *pl2 = 1; flags = PLAYER_2; tet = tetris2p+1; } else if (NETPLAY && sock_flags & SAME_HEIGHT && !player1.height) flags = DISCARD_MOVES; else flags = 0; if (tet->delay && (tet->falltm || *tet->clearedlines)) flags |= DISCARD_MOVES; return processkey_ingame(key, flags); } static int upd_player(struct player *plr, struct tetris2p *tet, int tm) { if (tet->delay) { tet->delay -= tm; if (tet->falltm) return tet->delay > 0; if (tet->b1) { if (!upd_lockdelay_state(plr, tet)) lockpiece_2p(plr, tet); } else if (tet->delay <= 0) { if (!draw_lineclear_step(plr, tet, 0)) spawndelay(plr, tet); } } else { tet->falltm -= tm; if (tet->falltm <= 0) { if (movedown(plr, 0)) tet->falltm = plr->falltime; else lockdelay(plr, tet); } } return 1; } static int startgame_wait_2p() { static struct tetr next = {0}; gettetrom(&next, *tetrom_seq); game->next = &next; return startgame_wait(0); } static int wait_next() { #ifdef SOCKET int t = gettm(0); while (*tetrom_seq==0x7F) { sock_getkeypress(0); if (sock_flags & CONN_BROKEN || !(sock_flags & PL2_IN_GAME) || gettm(t)-t >= 1000) return 0; } #endif return 1; } static int initround() { memset(tetris2p, 0, 2*sizeof(struct tetris2p)); winner = NULL; if (!NETPLAY || is_server) { gen_tetrom_seq(0, 8); show_next(&player1, *tetrom_seq); show_next(&player2, *tetrom_seq); } else { tetrom_seq = malloc(4); memset(tetrom_seq, 0x7F, 4); tetrom_seq_len = 4; tetrom_seq_pos[1] = 2; } if (NETPLAY) sock_initround(); if (!startgame_wait_2p()) return 0; if (NETPLAY) { if (*tetrom_seq==0x7F && !wait_next()) return 0; sock_sendbyte('.'); } return 1; } static int gameover_timeout(int *gameover) { if (!NETPLAY || is_server) return 1; #ifdef SOCKET if (*tetrom_seq==0x7F && !(sock_flags & PL2_IN_GAME)) { *gameover = 2; sock_flags |= PL2_IN_GAME; return 1; } if (*gameover == 1 && tetris2p[0].delay < 31768 && tetris2p[1].b1) return 1; if (*gameover == 3 && tetris2p[1].delay < 31768) { *gameover = 1 + (tetris2p[0].delay >= tetris2p[1].delay); return 1; } return 0; #endif } static void sync_spawn_delay() { if (NETPLAY && tetrom_seq_pos[0] == tetrom_seq_pos[1] && tetris2p[0].delay > 100 && tetris2p[1].delay > 100 && tetris2p[0].falltm && tetris2p[1].falltm == player1.falltime) { tetris2p[0].delay = tetris2p[1].delay; } } static void set_gameover(int *gameover, int i) { *gameover |= 1+i; if (NETPLAY && !is_server) { tetris2p[i].falltm = -1; tetris2p[i].delay = 0x7FFF; } } static void updateplayer(int *gameover, int i, int t) { struct player *plr = game->player+i; if (!upd_player(plr, tetris2p+i, gettm(t)-t) && !nextpiece_2p(plr)) set_gameover(gameover, i); } static struct player *play_round() { int gameover = 0; int t, i, ret; if (!initround()) return NULL; nextpiece_2p(&player1); nextpiece_2p(&player2); while (!gameover || !gameover_timeout(&gameover)) { if (NETPLAY && !(sock_flags & PL2_IN_GAME)) { sock_sendbyte(ESC); return &player1; } t = gettm(0); sync_spawn_delay(); ret = processkey(&i); if (ret == -2) return NULL; if (NETPLAY && i) { if (!tetris2p[1].delay && tetris2p[1].garbage[1]) { tetris2p[1].delay = 0x7FFF; set_gameover(&gameover, 1); } if (ret==1) sendnext(&player2); } if (!ret) lockpiece_2p(game->player+i, tetris2p+i); if (ret) updateplayer(&gameover, i, t); updateplayer(&gameover, !i, t); if (winner) return winner; } i = !(gameover & 1); if (!(game->mode & MODE_BTYPE) || game->player[i].lines) i = !i; if (gameover==3 && (!(game->mode & MODE_BTYPE) || !player1.lines == !player2.lines)) i = 2; winner = game->player+i; if (NETPLAY) sock_sendwinner(); return winner; } static int wait_gameover() { int tm = 2000; int t; game->state = GAME_OVER; do { t = gettm(0); switch (getkeypress(tm, IN_GAME) & 0x7F) { case ESC: return 0; case STARTBTN: return 1; } tm -= gettm(t)-t; } while (tm > 0); return processkey_ingame(getkeypress_block(0), DISCARD_MOVES) != -2; } int startgame_2p() { struct player *plr; player1.score = 0; player2.score = 0; drawgamescreen_2p(); if (NETPLAY) { if (!sock_wait_pl2ingame()) return 0; plr = &player2; if (plr->level != plr->startlevel) { setupplayer(plr); upd_stat(plr, 0); } } while (plr = play_round()) { free_tetrom_seq(); if (plr == game->player+2) /* draw */ plr = NULL; else { plr->score++; upd_stat(plr, 0); } show_winner(plr); if (plr && plr->score == 3) { #ifdef SOCKET if (NETPLAY && opponent_name[0]) upd_wonlost_stats(my_name, opponent_name, player1.score == 3); #endif ; } else plr = NULL; if (!wait_gameover() || plr) break; plr = &player1; if (NETPLAY && (SAME_HEIGHT|PL2_IN_GAME) == (sock_flags & (IS_SERVER|SAME_HEIGHT|PL2_IN_GAME))) plr->height = 0; while (1) { setupplayer(plr); redrawboard(plr, 19); upd_stat(plr, 0); upd_garbagemeter(plr, 0); hide_dropmarker(plr); if (isplayer2(plr)) break; plr++; } if (NETPLAY) { if (!(sock_flags & PL2_IN_GAME)) { game->state = 0; return startgame_2p(); } sock_sendbyte('s'); } } free_tetrom_seq(); game->state = 0; #ifdef SOCKET if (NETPLAY) { sock_flags &= ~PL2_IN_GAME; sock_sendbyte(ESC); } #endif return plr != NULL; } vitetris-0.58.0/src/game/tetris2p.h000066400000000000000000000006101344123051600170760ustar00rootroot00000000000000#ifdef SOCKET #define NETPLAY (game->mode & MODE_NETWORK) #else #define NETPLAY 0 #endif extern struct tetris2p { int falltm; int delay; char clearedlines[4]; char nul; signed char garbage[3]; signed char x1, x2; short b1, b2; } tetris2p[2]; extern struct player *winner; extern char *tetrom_seq; void getgarbage_player2(); int nextpiece_2p(struct player *plr); int startgame_2p(); vitetris-0.58.0/src/game/wonlost.c000066400000000000000000000053721344123051600170340ustar00rootroot00000000000000#include #include #include #include #include "game.h" #include "../options.h" #include "../cfgfile.h" static char *get_wonlost_stats_key(const char *me, const char *opp, char **key) { struct option *o = getoptions("wonlost"); char *s, *p; int n = strlen(opp); int m = strlen(me); for (; o; o = o->next) { s = opt_longstr(o); if (!s) continue; p = strrchr(s, ' '); if (m && !strncmp(s, me, m) && s[m] == ' ' && p > s+m) s += m + 1; if (p && isdigit(p[1]) && n == p-s && !strncmp(s, opp, n) && strlen(p) <= 8) { if (key) *key = opt_key(o); return p+1; } } return NULL; } const char *get_wonlost_stats(const char *me, const char *opponent) { char *s = get_wonlost_stats_key(me, opponent, NULL); if (s) return s; return "0-0"; } static int key2index(const char *key) { int i; if (key[2] || !islower(key[0])) return -1; i = key[0] - 'a'; if (key[1]) { if (!islower(key[1])) return -1; i *= 26; i += key[1] - 'a'; } return i; } static int get_next_index(int next_index, struct option *first, struct option *end) { struct option *o = first; for (; o != end; o = o->next) if (key2index(opt_key(o)) == next_index) next_index = get_next_index(next_index+1, first, o); return next_index; } static int get_any_index(struct option *first, const char *me) { struct option *o = first; const char *s; int n = strlen(me); for (; o != NULL; o = o->next) { s = opt_longstr(o); if (!s || strncmp(s, me, n)) return key2index(opt_key(o)); } return get_any_index(first, ""); } static void setopt_wonlost(const char *key, const char *me, const char *opp, const char *stats) { union val val; char buf[44]; sprintf(buf, "%s %s %s", me, opp, stats); val.p = buf; setoption("wonlost", key, val, 2); } static void add_wonlost_stats(const char *me, const char *opp, int won) { struct option *first = getoptions("wonlost"); char key[4] = ""; int i = get_next_index(0, first, NULL); if (i >= 640) i = get_any_index(first, me); key[0] = 'a' + i / 26; key[1] = 'a' + i % 26; setopt_wonlost(key, me, opp, won ? "1-0" : "0-1"); } void upd_wonlost_stats(const char *me, const char *opponent, int won) { char stats[8]; char *key; union val val; char *s, *p; int loss = 0; readoptions(); s = get_wonlost_stats_key(me, opponent, &key); if (!s) add_wonlost_stats(me, opponent, won); else { if (won) won = 1; else loss = 1; p = strchr(s, '-'); if (p && isdigit(p[1])) { won += atoi(s); loss += atoi(p+1); if (won >= 1000) won = 999; if (loss >= 1000) loss = 999; } sprintf(stats, "%d-%d", won, loss); if (strlen(stats) <= strlen(s)) strcpy(s, stats); else setopt_wonlost(key, me, opponent, stats); } writeconfig(); } vitetris-0.58.0/src/hiscore.c000066400000000000000000000150001344123051600160370ustar00rootroot00000000000000#include #include #include "hiscore.h" #include "cfgfile.h" #include "lang.h" #include "game/tetris.h" #include "config.h" struct hiscore hiscores[10] = {{"", 0}}; static const char last_chars[8] = "ZÅÄÖ!?Ü"; void writehiscores(FILE *fp); static void addhiscore(struct hiscore *hs) { int i; if (hs->score > hiscores[0].score) i = 0; else { i = 10; while (hs->score > hiscores[i-1].score) i--; if (i == 10 || hs->score == hiscores[i-1].score && hs->lines == hiscores[i-1].lines && !strcmp(hs->name, hiscores[i-1].name)) return; } memmove(hiscores+i+1, hiscores+i, (9-i)*sizeof(struct hiscore)); hiscores[i] = *hs; } /* valid characters [A-Z0-9 .!?-ÅÄÖÜ] */ static int encodehiscore_name(const char *name, FILE *fp, int backcomp) { int doshack = 0; char s[8]; int i; unsigned char c; char *p; for (i = 0; c = name[i]; i++) { if (c == ' ') c = 3; else if (p = strchr(last_chars, c)) c = 44 + p - last_chars; else if (c <= '9') c -= 44 - (c >= '6'); else c -= 50; s[i] = c; } s[i] = 60; if (i < 7) s[i+1] = '\0'; i = 0; while (i < 8 && s[i]) { switch (i % 4) { case 0: c = s[i] | (s[i+1] & 3)<<6; if (c =='\r' && !backcomp) { c = 255; doshack = 1; } break; case 1: c = s[i]>>2 | (s[i+1] & 15)<<4; break; case 2: c = s[i]>>4 | s[i+1]<<2; i++; } if (!c || c == '\n') c = 255; /* Ctrl-Z means end-of-file in MS text mode */ else if (c == 0x1A && !backcomp) { c = 254; doshack = 1; } putc(c, fp); if (!s[i]) break; i++; } return doshack; } static int decodehiscore_name(unsigned char *line, char *dest) { int len = strlen(line); int i = 0; int j = 0; unsigned char c; while (i < 8) { if (j >= len) return 0; if (line[j] == 254) line[j] = 0x1A; /* Ctrl-Z */ switch (i % 4) { case 0: if (line[j] == 255) line[j] = '\r'; c = line[j] & 63; break; case 1: c = line[j] >> 6; j++; if (line[j] == 255) line[j] = 0; c |= (line[j] & 15) << 2; break; case 2: c = line[j] >> 4; j++; if (line[j] == 255) line[j] = '\n'; c |= (line[j] & 3) << 4; break; case 3: c = line[j] >> 2; j++; } if (c == 60) break; if (c == 0) return 0; if (c == 3) c = ' '; else if (c < 15) c += 44 - (c > 10); else if (c < 40) c += 50; else if (c >= 44 && c <= 50) c = last_chars[c-44]; else return 0; dest[i] = c; i++; } dest[i] = '\0'; if (i < 8 && i%4 < 3) j++; if (j > len) return 0; return j; } static int encodehiscore(struct hiscore *hs, FILE *fp, int backcomp) { uint_least32_t d; int doshack = encodehiscore_name(hs->name, fp, backcomp); int c; d = hs->score; do { c = (d & 127)+20; if (c == 0x1A && !backcomp) { c = 19; doshack = 1; } putc(c, fp); } while (d >>= 7); putc((hs->score & 7)+2, fp); d = hs->startlevel+97+(hs->score & 7); putc(d, fp); putc(hs->level+d, fp); d = hs->lines; do putc((d & 63)+64, fp); while (d >>= 6); return doshack; } static int iseol(int c) { return !c || c =='\n' || c=='\r'; } static int decodehiscore(unsigned char *line, struct hiscore *hs) { int i = decodehiscore_name(line, hs->name); int c; if (!i || iseol(line[i])) return 0; line += i; if (line[0] == 19) line[0] = 0x1A; c = (line[0]-20 & 7)+2; for (i = 1; line[i] != c; i++) if (iseol(line[i])) return 0; c = i; hs->score = 0; while (i) { i--; hs->score <<= 7; if (line[i] < 19) return 0; hs->score |= line[i]-20; } i = c+1; if (iseol(line[i]) || iseol(line[i+1])) return 0; hs->level = line[i+1]-line[i]; c = line[i]-97-(hs->score & 7); if (c < 0 || c > 10 || hs->level < c) return 0; hs->startlevel = c; line += i+2; i = 0; while (!iseol(line[i])) i++; if (!i) return 0; hs->lines = 0; while (i) { i--; hs->lines <<= 6; if (line[i] < 64) return 0; hs->lines |= line[i]-64; } return 1; } static int readhiscores_fp(FILE *fp, char *line, int try) { struct hiscore hs; while (fgets(line, 16, fp)) { if (decodehiscore(line, &hs)) addhiscore(&hs); else if (try) return 0; try = 0; } fclose(fp); return 1; } static void readhiscores_config(FILE *fp, char *line) { while (fgets(line, 16, fp)) if (line[0] == '[' && !strncmp(line+1, "hiscore", 7)) break; if (!feof(fp)) readhiscores_fp(fp, line, 0); else fclose(fp); } static void mergehiscores(const char *filename, char *line) { FILE *fp; fp = fopen(filename, "r"); if (fp && !readhiscores_fp(fp, line, 1)) readhiscores_config(fp, line); } #ifdef UNIX static int savehiscores_global() { FILE *fp = fopen(HISCORE_FILENAME, "w"); if (!fp) return 0; writehiscores(fp); fclose(fp); return 1; } #else #define savehiscores_global() 0 #endif int readhiscores(const char *filename) { FILE *fp; char line[16]; if (filename) mergehiscores(filename, line); if (fp = fopen(cfgfilename, "r")) readhiscores_config(fp, line); #ifdef UNIX if (fp = fopen(HISCORE_FILENAME, "r")) readhiscores_fp(fp, line, 0); if (filename) savehiscores_global(); #endif return (hiscores[0].score != 0); } void writehiscores(FILE *fp) { char doshack[10] = {0}; int i = 0; while (i < 10 && hiscores[i].score) { doshack[i] = encodehiscore(&hiscores[i], fp, 0); putc('\n', fp); i++; } #ifdef UNIX for (i=0; i < 10; i++) if (doshack[i]) { encodehiscore(&hiscores[i], fp, 1); putc('\n', fp); } #endif } int savehiscore(const char *name) { struct hiscore hs; int n = strlen(name); if (!n) return 1; while (name[n-1] ==' ') n--; if (!n) return 1; strcpy(hs.name, name); hs.name[n] = '\0'; hs.score = player1.score; hs.startlevel = player1.startlevel; hs.level = player1.level; hs.lines = player1.lines; addhiscore(&hs); n = writeconfig(); return (savehiscores_global() || n); } const char *gethiscorename(int i, char *buf) { const char lat1[5] = "ÅÄÖÜ"; const char ascii[5] = "AAOU"; const char *nm = hiscores[i].name; const char *p; if (lang & LATIN1) return nm; i = 0; while (*nm) { if (p = strchr(lat1, *nm)) buf[i] = ascii[p-lat1]; else buf[i] = *nm; nm++; i++; } buf[i] = '\0'; return buf; } int gethiscorelist(char *s) { char name[8]; struct hiscore *hs; int i = 0; int n; while (i < 10 && hiscores[i].score) { hs = hiscores+i; n = sprintf(s, "%2d. %s", i+1, gethiscorename(i, name)); memset(s+n, ' ', 12-n); s += 12; n = sprintf(s, "%7ld %d-%d", (long) hs->score, hs->startlevel, hs->level); memset(s+n, ' ', 15-n); s += 15; sprintf(s, "%3d", hs->lines); strcpy(s+3, i<9 ? " \n" : "\n"); s += 5; i++; } return i; } vitetris-0.58.0/src/hiscore.h000066400000000000000000000011251344123051600160470ustar00rootroot00000000000000#include "int32t.h" extern struct hiscore { char name[8]; int_least32_t score; char startlevel; char level; short lines; } hiscores[10]; #define ishiscore() (player1.score >= 12000 && \ player1.score > hiscores[9].score) int readhiscores(const char *filename); /* returns 0 if highscore could not be saved */ int savehiscore(const char *name); /* returns hiscores[i].name or buf */ const char *gethiscorename(int i, char *buf); /* Get formatted hiscorelist in buf, which should be of size 320. * every row is 32 chars * returns number of rows */ int gethiscorelist(char *buf); vitetris-0.58.0/src/input/000077500000000000000000000000001344123051600154025ustar00rootroot00000000000000vitetris-0.58.0/src/input/Makefile000066400000000000000000000040621344123051600170440ustar00rootroot00000000000000include ../src-conf.mk OBJS = input.o keyboard.o joystick.o playerin.o default: $(BACKEND) unixterm: $(OBJS) inp_unixterm.o escseq.o select.o $(joylinux_obj) rm -f input.a ar rcs input.a $(OBJS) inp_unixterm.o escseq.o select.o $(joylinux_obj) curses: $(OBJS) inp_curses.o $(joylinux_obj) $(select_obj) rm -f input.a ar rcs input.a $(OBJS) inp_curses.o $(joylinux_obj) $(select_obj) conio: $(OBJS) inp_con.o rm -f input.a ar rcs input.a $(OBJS) inp_con.o allegro: $(OBJS) inp_allegro.o $(select_obj) rm -f input.a ar rcs input.a $(OBJS) inp_allegro.o $(select_obj) input.o: input.c input.h keyboard.h joystick.h \ ../timer.h ../draw/draw.h ../game/tetris.h ../netw/sock.h \ ../textgfx/textgfx.h ../focus.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(DTWOPLAYER) $(DJOYSTICK) $(DSOCKET) $(DTTY_SOCKET) $(DNO_MENU) $(DTERM_RESIZING) $(DXLIB) $(DALLEGRO) -c input.c keyboard.o: keyboard.c keyboard.h input.h escseq.h \ ../config.h ../config2.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(DTWOPLAYER) $(DCURSES) $(DALLEGRO) -c keyboard.c joystick.o: joystick.c joystick.h input.h ../timer.h joylinux.o: joylinux.c joystick.h input.h ../timer.h ../options.h inp_unixterm.o: inp_unixterm.c termin.h keyboard.h escseq.h input.h select.h \ joystick.h ../src-conf.mk $(CC) $(CCFLAGS) $(DJOYSTICK) $(DSOCKET) -c inp_unixterm.c escseq.o: escseq.c escseq.h input.h termin.h ../src-conf.mk $(CC) $(CCFLAGS) $(DTWOPLAYER) -c escseq.c select.o: select.c select.h input.h ../textgfx/textgfx.h \ ../config.h ../config2.h $(CC) $(CCFLAGS) -I.. -c select.c inp_curses.o: inp_curses.c termin.h keyboard.h input.h $(CC) $(CCFLAGS) $(CURSES_INC) -c inp_curses.c inp_con.o : inp_con.c termin.h keyboard.h input.h inp_allegro.o: inp_allegro.c keyboard.h joystick.h input.h \ ../timer.h ../game/tetris.h ../textgfx/textgfx.h \ ../textgfx/alleg.h ../config.h $(CC) $(CCFLAGS) -I.. -c inp_allegro.c playerin.o: playerin.c input.h ../options.h .c.o: $(CC) $(CCFLAGS) -c $< clean: rm -f input.a *.o rm -f inp_c~70.o inp_a~m7.o .PHONY: default unixterm curses con allegro clean vitetris-0.58.0/src/input/escseq.c000066400000000000000000000060061344123051600170330ustar00rootroot00000000000000#include #include #include #include #include "escseq.h" #include "input.h" #include "termin.h" static struct escseq { char str[3]; unsigned char keypress; struct escseq *next; } escseq_singlepl; #ifdef TWOPLAYER static struct escseq escseq_1p, escseq_2p; #endif /* wait 1 millisecond for input */ static int readchr_wait() { if (waitinput_stdin(1)) return readchr(); return 0; } int readescseq(char *s) { /* wait 55 ms before returning ESC */ int c = waitinput_stdin(55) ? readchr() : 0; if (c == '[') { c = readchr_wait(); if (!c) return -1; switch (c) { case 'A': return MVUP; case 'B': return MVDOWN; case 'C': return MVRIGHT; case 'D': return MVLEFT; case '3': if ((c = readchr()) == '~') return DEL; if (c) unreadchr = c; c = '3'; } s[0] = '['; s[1] = c; s[2] = readchr_wait(); if (isdigit(c) && isdigit(s[2])) readchr_wait(); } else { if (!c) return ESC; if (c == ESC) { unreadchr = ESC; return ESC; } s[0] = c; if (s[1] = readchr_wait()) s[2] = readchr_wait(); } s[3] = '\0'; return 0; } static struct escseq *getescseq(int flags) { #ifdef TWOPLAYER if (flags & PLAYER_1) return &escseq_1p; else if (flags & PLAYER_2) return &escseq_2p; else #endif return &escseq_singlepl; } int transl_escseq(const char *s, int flags) { struct escseq *e; int ret; #ifdef TWOPLAYER if (!(flags & SINGLE_PL)) { if (ret = transl_escseq(s, flags | PLAYER_1 | SINGLE_PL)) return ret | PLAYER_1; if (ret = transl_escseq(s, flags | PLAYER_2 | SINGLE_PL)) return ret | PLAYER_2; return 0; } #endif e = getescseq(flags); ret = 0; do if ((flags & IN_GAME || !(e->keypress & 0x80)) && !strncmp(s, e->str, 3)) { ret = e->keypress; if (ret & 0x80) ret ^= 0x80; else if (flags & IN_GAME) continue; break; } while (e = e->next); return ret; } const char *getescseq_str(int keypr) { struct escseq *e = getescseq(keypr); unsigned char k = keypr | (keypr & IN_GAME) >> 1; do if (k == e->keypress) return e->str; while (e = e->next); return ""; } void mapescseq(const char *str, int keypr) { struct escseq *e = getescseq(keypr); unsigned char k = keypr | (keypr & IN_GAME) >> 1; if (e->keypress) { while (k != e->keypress) { if (!e->next) { e = e->next = malloc(sizeof(struct escseq)); e->next = NULL; break; } e = e->next; } } memcpy(e->str, str, 3); e->keypress = k; } void rmescseq(int keypress) { struct escseq *e, *p; unsigned char keypr = keypress | (keypress & IN_GAME) >> 1; e = getescseq(keypress); if (keypr == e->keypress) { e->keypress = 0; return; } while (e->next) { if (keypr == e->next->keypress) { p = e->next->next; free(e->next); e->next = p; break; } e = e->next; } } static void freeescseq(struct escseq *hd) { struct escseq *e; while (e = hd->next) { hd->next = e->next; free(e); } } void free_escape_sequences() { freeescseq(&escseq_singlepl); #ifdef TWOPLAYER freeescseq(&escseq_1p); freeescseq(&escseq_2p); #endif } vitetris-0.58.0/src/input/escseq.h000066400000000000000000000004631344123051600170410ustar00rootroot00000000000000#include "../config.h" #if UNIX && !CURSES && !ALLEGRO #define ESCSEQ 1 #endif int readchr(); int readescseq(char *s); int transl_escseq(const char *s, int flags); const char *getescseq_str(int keypr); void mapescseq(const char *str, int keypr); void rmescseq(int keypress); void free_escape_sequences(); vitetris-0.58.0/src/input/inp_allegro.c000066400000000000000000000165631344123051600200540ustar00rootroot00000000000000#include #include /* sprintf */ #include "../config.h" #include #include "keyboard.h" #include "joystick.h" #include "input.h" #include "../timer.h" #include "../game/tetris.h" #include "../textgfx/textgfx.h" /* refreshscreen */ #include "../textgfx/alleg.h" /* toggle_fullscreen */ static short key_tm[KEY_MAX]; static int temp_autorep_key; static char arrow_keys[8] = {KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN}; static struct js { short btns_tm[32]; short axis_tm[2]; char axis[2]; } joysticks[2]; void init_keybd() { install_keyboard(); set_keyboard_rate(0, 0); } void init_joysticks() { install_joystick(JOY_TYPE_AUTODETECT); if (num_joysticks > 0) { inputdevs_fd[1] = 1; js_default_buttons(0); num_joyst = 1; if (num_joysticks > 1) { inputdevs_fd[2] = 1; js_default_buttons(1); num_joyst = 2; } } } static int readshiftkey() { const shift_keys[6] = { KEY_LSHIFT, KEY_RSHIFT, KEY_LCONTROL, KEY_RCONTROL, KEY_ALT, KEY_ALTGR }; int scan; int i; for (i=0; i < 6; i++) { scan = shift_keys[i]; if (key[scan] && !key_tm[scan]) return scan; } return 0; } static void update_key_tm(int i) { char *p; int tm; if (i) { if (edit_mode) memset(key_tm, 0, KEY_MAX * sizeof(short)); key_tm[i] = gettm(0); p = memchr(arrow_keys, i, 8); if (p) { i = p - arrow_keys; if (i%4 < 2 || !game || !game_running) { if ((i%4)%2 == 0) i++; else i--; key_tm[arrow_keys[i]] = -1; } } } for (i=1; i < KEY_MAX; i++) if (key_tm[i] && !key[i]) key_tm[i] = 0; } static void setarrowkey(int scan, int press) { char *p = arrow_keys; if (press & PLAYER_2) p += 4; p[(press & 7)-1] = scan; } static int scan_to_ascii(int scan) { if (scan >= KEY_0_PAD && scan <= KEY_9_PAD) return 0; switch (scan) { case KEY_BACKSPACE: return '\b'; case KEY_DEL: return DEL; } return scancode_to_ascii(scan); } static int getautorep_key(int *ascii) { int flags = 0; int press; int i; for (i=1; i < KEY_MAX; i++) { if (key_tm[i] > 0 && key[i] && test_autorep_tm(key_tm+i)) { *ascii = scan_to_ascii(i); break; } } if (i == KEY_TAB) return KEY_TAB; if (i == KEY_MAX || kb_no_autorep) return 0; if (edit_mode && (i == KEY_BACKSPACE || i == KEY_DEL)) return i; if (game && game_running) flags |= IN_GAME; if (!game || (game->mode&(MODE_2PLAYER|MODE_NETWORK)) != MODE_2PLAYER) flags |= SINGLE_PL; temp_autorep_key = i<<8 | *ascii; press = kb_getpress(flags); temp_autorep_key = 0; if (!press) return 0; if ((press & 0x7F) <= MVRIGHT) { setarrowkey(i, press); return i; } if (flags & IN_GAME) { if ((press & 0x7F) == MVDOWN) { key_tm[i] -= DAS_DELAY/2; return i; } } else if ((press & 0x7F) <= MVDOWN) { setarrowkey(i, press); return i; } else if (autorep_a_b_btns) switch (press & 0x7F) { case A_BTN: case B_BTN: return i; } return 0; } int kb_readkey(unsigned char *dest) { int val = 0; int scan; if (temp_autorep_key) { val = temp_autorep_key; scan = val >> 8; temp_autorep_key = 1; } else { refreshscreen(); if (keypressed()) { val = readkey(); scan = val >> 8; if (scan == KEY_ENTER && key_shifts & KB_ALT_FLAG) { toggle_fullscreen(); kb_flushinp(); return 0; } } else scan = readshiftkey(); update_key_tm(scan); if (!scan) scan = getautorep_key(&val); } if (!scan) return 0; if (scan >= KEY_A && scan <= KEY_Z && !edit_mode) { val = scan+'a'-KEY_A; /* caps lock ignored */ if (key_shifts & KB_SHIFT_FLAG) val -= 'a'-'A'; } if (scan >= KEY_LEFT && scan <= KEY_DOWN) val = scan+MVLEFT-KEY_LEFT; else if (scan == KEY_DEL) val = DEL; else if (scan >= KEY_0_PAD && scan <= KEY_9_PAD) val = 0; else val &= 0xFF; if (val) { if (val == '\r') val = '\n'; dest[0] = val; return 1; } dest[0] = 0; dest[1] = scan; return 2; } int kb_toascii(const unsigned char *key) { int scan = key[1]; if (scan >= KEY_0_PAD && scan <= KEY_9_PAD) return scan-KEY_0_PAD+'0'; return ESC+1; } static int key_is_softdrop(int k, int pl) { int pl2; temp_autorep_key = k<<8 | scan_to_ascii(k); k = kb_getpress(IN_GAME); temp_autorep_key = 0; pl2 = k & PLAYER_2; if (pl==1 && pl2 || pl==2 && !pl2) return 0; return (k & 0x7F) == MVDOWN; } void kb_reset_drop(int pl) { int i; if (pl && inputdevs_player[0]) { if (pl != inputdevs_player[0]) return; pl = 0; } for (i=1; i < KEY_MAX; i++) if (key_tm[i] > 0 && key_is_softdrop(i, pl)) key_tm[i] = gettm(0); } void kb_flushinp() { clear_keybuf(); memset(key_tm, 0, KEY_MAX * sizeof(short)); temp_autorep_key = 0; } const char *kb_keyname(unsigned char *key, int n) { static char numstr[6] = "NUM "; int scan; const char *name; if (n < 2) return NULL; scan = key[1]; switch (scan) { case KEY_LSHIFT: return "LSHFT"; case KEY_RSHIFT: return "RSHFT"; case KEY_LCONTROL: return "LCTRL"; case KEY_RCONTROL: return "RCTRL"; case KEY_ALT: return "ALT"; case KEY_ALTGR: return "ALTGR"; } if (scan >= KEY_0_PAD && scan <= KEY_9_PAD) { numstr[4] = scan-KEY_0_PAD+'0'; return numstr; } name = scancode_to_name(key[1]); if (strlen(name) <= 5) return name; sprintf(key, "0+%X", key[1]); return key; } static void js_update() { int n; poll_joystick(); n = num_joysticks; if (n > 2) n = 2; if (n != num_joyst) { num_joyst = n; inputdevs_fd[1] = -1; inputdevs_fd[2] = -1; if (n > 0) { inputdevs_fd[1] = 1; if (n > 1) inputdevs_fd[2] = 1; } } } static int readaxis(int i, int j) { int axis = 0; int b = 0; if (joy[i].stick[0].axis[j].d1 == joy[i].stick[0].axis[j].d2) ; else if (joy[i].stick[0].axis[j].d1) { axis = -1; b = MVLEFT; } else { axis = 1; b = MVRIGHT; } if (axis == joysticks[i].axis[j]) return 0; joysticks[i].axis[j] = axis; if (!axis) return 0; joysticks[i].axis_tm[j] = gettm(0); if (j) b += 2; return b; } int js_readbtn(int i) { int a, b; js_update(); if (i >= num_joyst) return 0; b = 0; a = readaxis(i, 0); if (a) b = a; a = readaxis(i, 1); if (a) b = a; for (a=0; a < 32 && a < joy[i].num_buttons; a++) { if (!joy[i].button[a].b) joysticks[i].btns_tm[a] = 0; else if (!b && !joysticks[i].btns_tm[a]) { b = a+'0'; joysticks[i].btns_tm[a] = -1; } } return b; } void js_pressbtn(int i, int b) { joysticks[i].btns_tm[b-'0'] = gettm(0); } void js_releasebtn(int i, int b) { joysticks[i].btns_tm[b-'0'] = -1; } int js_pressed(int i) { struct js *js = joysticks+i; int n = 32; if (i < num_joysticks) { if (js->axis[0] || js->axis[1]) return 1; if (n > joy[i].num_buttons) n = joy[i].num_buttons; for (i=0; i < n; i++) if (js->btns_tm[i] > 0) return 1; } return 0; } int js_autorep(int i, short **tm_ret) { struct js *js = joysticks+i; int n = 32; if (js->axis[0] && test_autorep_tm(js->axis_tm)) { *tm_ret = js->axis_tm; return MVLEFT+(js->axis[0] > 0); } if (js->axis[1] && test_autorep_tm(js->axis_tm+1)) { *tm_ret = js->axis_tm+1; return MVUP + (js->axis[1] > 0); } if (n > joy[i].num_buttons) n = joy[i].num_buttons; for (i=0; i < n; i++) if (js->btns_tm[i] > 0 && test_autorep_tm(js->btns_tm+i)) { *tm_ret = js->btns_tm+i; return i+'0'; } return 0; } void js_reset_drop(int i) { struct js *js = joysticks+i; int n = 32; js->axis_tm[1] = gettm(0); if (n > joy[i].num_buttons) n = joy[i].num_buttons; for (i=0; i < n; i++) if (js->btns_tm[i] > 0) js->btns_tm[i] = gettm(0); } int inpselect_dev(int tm) { return 0; } vitetris-0.58.0/src/input/inp_con.c000066400000000000000000000015711344123051600171770ustar00rootroot00000000000000#include #include /* sprintf */ #include "termin.h" #include "keyboard.h" #include "input.h" void set_input_mode() {} void restore_input_mode() {} void init_keybd() {} int kb_readkey(unsigned char *dest) { int c; if (!kbhit()) return 0; c = getch(); if (!c || c==0xE0) { c = getch(); switch (c) { case 75: c = MVLEFT; break; case 77: c = MVRIGHT; break; case 72: c = MVUP; break; case 80: c = MVDOWN; break; case 83: c = DEL; break; default: dest[0] = '\0'; dest[1] = c; return 2; } } else if (c =='\r') c ='\n'; *dest = c; return 1; } int kb_toascii(const unsigned char *key) { return ESC+1; } void kb_flushinp() { while (kbhit()) getch(); } const char *kb_keyname(unsigned char *key, int n) { if (n < 2) return NULL; sprintf(key, "0+%X", key[1]); return key; } int inpselect_dev(int tm) { return 0; } vitetris-0.58.0/src/input/inp_curses.c000066400000000000000000000037441344123051600177300ustar00rootroot00000000000000#include #include "termin.h" #include "keyboard.h" #include "input.h" void set_input_mode() { cbreak(); noecho(); keypad(stdscr, TRUE); nodelay(stdscr, TRUE); #ifdef PDCURSES PDC_return_key_modifiers(TRUE); #endif } void init_keybd() {} int kb_readkey(unsigned char *dest) { const short funckeys[7] = { KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_ENTER, KEY_BACKSPACE, KEY_DC }; const unsigned char keys[7] = { MVLEFT, MVRIGHT, MVUP, MVDOWN, STARTBTN, BACKSPACE, DEL }; int c = getch(); int i; if (c == ERR) return 0; #if PDCURSES && (WIN32 || __WIN32__) /* PDCurses 3.3 in Win 98 workarounds. */ /* I get 0xCA|character every now and then */ if (c > KEY_MAX) c &= 0xff; /* I get right shift after arrow keys all the time */ if (c == KEY_SHIFT_R) return 0; #endif #ifdef KEY_RESIZE if (c == KEY_RESIZE) return 0; #endif for (i=0; i<7; i++) if (c == funckeys[i]) { dest[0] = keys[i]; return 1; } #ifdef PADENTER if (c == PADENTER) { dest[0] = STARTBTN; return 1; } #endif if (c >= 0x100) { dest[0] = c & 0xFF; dest[1] = c >> 8; return 2; } dest[0] = c; return 1; } int kb_toascii(const unsigned char *key) { short numpad[10] = { #ifdef PDCURSES PAD0, KEY_C1, KEY_C2, KEY_C3, KEY_B1, KEY_B2, KEY_B3, KEY_A1, KEY_A2, KEY_A3 #else 0, KEY_C1, 0, KEY_C3, 0, KEY_B2, 0, KEY_A1, 0, KEY_A3 #endif }; int ch = key[0] | key[1] << 8; int i; for (i=0; i < 10; i++) if (numpad[i] == ch) return i+'0'; return ESC+1; } void kb_flushinp() { flushinp(); } const char *kb_keyname(unsigned char *key, int n) { unsigned c; if (n < 2) return NULL; c = key[0]; c |= key[1] << 8; #ifdef PDCURSES switch (c) { case KEY_SHIFT_L: return "LSHFT"; case KEY_SHIFT_R: return "RSHFT"; case KEY_CONTROL_L: return "LCTRL"; case KEY_CONTROL_R: return "RCTRL"; case KEY_ALT_L: return "ALT"; case KEY_ALT_R: return "ALTGR"; } #endif sprintf(key, "%X", c); return key; } int inpselect_dev(int tm) { return 0; } vitetris-0.58.0/src/input/inp_unixterm.c000066400000000000000000000047771344123051600203060ustar00rootroot00000000000000#include #include #include #include /* atexit */ #include /* strlen */ #include "select.h" #include "termin.h" #include "keyboard.h" #include "escseq.h" #include "input.h" #include "joystick.h" /* js_pressed */ #ifdef JOYSTICK #define JS_PRESSED (js_pressed(0) || js_pressed(1)) #else #define JS_PRESSED 0 #endif char unreadchr = '\0'; static struct termios saved_term_attr; void set_input_mode() { struct termios attr; tcgetattr(STDIN_FILENO, &saved_term_attr); tcgetattr(STDIN_FILENO, &attr); attr.c_lflag &= ~(ICANON|ECHO); attr.c_cc[VMIN] = 0; attr.c_cc[VTIME] = 2; tcsetattr(STDIN_FILENO, TCSADRAIN, &attr); atexit(free_escape_sequences); } void restore_input_mode() { tcsetattr(STDIN_FILENO, TCSANOW, &saved_term_attr); } int readchr() { int ret; if (!unreadchr) { if (!waitinput_stdin(0)) return 0; ret = read(STDIN_FILENO, &unreadchr, 1); if (ret <= 0) return 0; } ret = (unsigned char) unreadchr; unreadchr = '\0'; return ret; } int waitinput_stdin(unsigned msec) { return waitinput(STDIN_FILENO, msec); } void init_keybd() { inputdevs_fd[0] = STDIN_FILENO; } int kb_readkey(unsigned char *dest) { int c = readchr(); if (!c) return 0; if (c == ESC) switch (c = readescseq((char *) dest+1)) { case -1: return 0; case 0: dest[0] = ESC; return strlen((char *) dest); } else if (c == DEL) c = BACKSPACE; *dest = c; return 1; } int kb_toascii(const unsigned char *key) { return ESC+1; } void kb_flushinp() { while (readchr()) ; } const char *kb_keyname(unsigned char *key, int n) { if (n < 2) return NULL; memmove(key+3, key+1, n); memcpy(key, "ESC", 3); return (const char *) key; } static void settimeout(struct timeval *tmv, int ms) { if (ms > 5 && JS_PRESSED) { tmv->tv_sec = 0; tmv->tv_usec = 5000; } else { tmv->tv_sec = ms/1000; tmv->tv_usec = 1000*(ms%1000); } } static int setfds(fd_set *set) { #if NUM_INPUTDEVS > 1 int n = 0; int i = NUM_INPUTDEVS-1; FD_ZERO(set); while (i >= 0) { if (inputdevs_fd[i] > -1) { FD_SET(inputdevs_fd[i], set); if (inputdevs_fd[i] >= n) n = inputdevs_fd[i]+1; } i--; } return n; #else FD_ZERO(set); FD_SET(STDIN_FILENO, set); return STDIN_FILENO+1; #endif } int inpselect_dev(int tm) { fd_set set; struct timeval tmv; int i; settimeout(&tmv, tm); if (inpselect(setfds(&set), &set, &tmv) <= 0) return NUM_INPUTDEVS; for (i=0; i < NUM_INPUTDEVS; i++) if (inputdevs_fd[i] > -1 && FD_ISSET(inputdevs_fd[i], &set)) break; return i; } vitetris-0.58.0/src/input/input.c000066400000000000000000000153001344123051600167040ustar00rootroot00000000000000#include #include /* sprintf */ #include /* exit */ #include "input.h" #include "keyboard.h" #include "joystick.h" #include "../timer.h" #include "../draw/draw.h" /* upd_screen */ #include "../game/tetris.h" #ifndef SOCKET #define SOCKET_EMPTY_DEFS 1 #undef socket_fd #define socket_fd -1 #endif #include "../netw/sock.h" #include "../textgfx/textgfx.h" /* upd_termresize */ #include "../focus.h" extern int close_button_pressed; const char input_chr9[9][4] = { "LFT", "RGT", "UP", "DWN", "(A)", "(B)", "BEL", "BS", "HT" }; int inputdevs_fd[4] = {-1,-1,-1,-1}; char inputdevs_player[4] = {0}; int autorep_a_b_btns = 0; int edit_mode = 0; static short spawn_tm[2]; static int ignore_dev; void init_inputdevs() { init_keybd(); #if JOYSTICK init_joysticks(); #endif } #if TWOPLAYER && NUM_INPUTDEVS > 1 static int player_flag(int i, int flags) { if (socket_fd > -1) { if (i==3) return PLAYER_2; } else if (inputdevs_player[i] && !(flags & SINGLE_PL)) return inputdevs_player[i]==1 ? PLAYER_1 : PLAYER_2; return 0; } #else #define player_flag(i, flags) 0 #endif static int getkeypress_select(int tm, int flags) { int keypress = 0; int i; #if TERM_RESIZING if (tm > 80) upd_termresize(); #endif #if XLIB || ALLEGRO if (tm > 80 && in_xterm && game && game_running && !TWOPLAYER_MODE && !xterm_hasfocus()) return STARTBTN; #endif for (i = inpselect_dev(tm); i < NUM_INPUTDEVS && !keypress; i++) { if (i+1 == ignore_dev) continue; switch (i) { case 0: keypress = kb_getpress(flags); break; #if JOYSTICK case 1: case 2: keypress = js_getpress(i-1, flags); break; #endif #if SOCKET case 3: keypress = sock_getkeypress(flags); if (ignore_dev) return 0; #endif } } if (keypress) keypress |= player_flag(i-1, flags); return keypress; } int getkeypress(int tm, int flags) { int t = gettm(0); int keypress; if (socket_fd > -1) flags |= SINGLE_PL; while (1) { if (tm <= 0) return 0; keypress = getkeypress_select(tm, flags); #if JOYSTICK if (!keypress) keypress = getautorepeat(flags); #endif if (keypress) break; if (gettm(t) == t) sleep_msec(1); tm -= gettm(t)-t; t = gettm(0); #ifdef ALLEGRO if (close_button_pressed) exit(0); #endif } return keypress; } int getkeypress_block(int flags) { int keypress; while (1) { #if TTY_SOCKET && !NO_MENU if (!(flags & 1) && (invit || checkinvit())) return ESC; #endif keypress = getkeypress(1000, flags); if (keypress) break; sleep_msec(55); } return keypress; } void spawn_discard_drops(int pl) { int i = 0; if (pl==2) { i = 1; if (socket_fd > -1) { spawn_tm[1] = 0; return; } } spawn_tm[i] = gettm(0); #ifdef ALLEGRO kb_reset_drop(pl); #endif #ifdef JOYSTICK if (!num_joyst) return; i = !js_pressed(0); if (pl==2 && inputdevs_player[i+1] != 2) { if (i || inputdevs_player[2] != 2) return; i = 1; } if (js_pressed(i)) js_reset_drop(i); #endif } static int key_is_valid(unsigned c, int keypr) { return c == (keypr & 0x7F) || c > MVRIGHT && (c > MVDOWN || keypr & IN_GAME) && c != STARTBTN && c != '\t'; } static int setkeymapping_keybd(int keypr) { unsigned char s[5] = ""; unsigned c; kb_no_autorep = 1; while (!kb_readkey(s)) { if (c = getkeypress_select(100, SINGLE_PL)) return c; sleep_msec(55); } c = !s[1] ? s[0] : ESC+1; if (c == ESC) kb_rmmapping(keypr); else { if (!key_is_valid(c, keypr)) return c; if (c == MVUP && (keypr & (63 | IN_GAME)) == MVUP) { c = kb_getchrfor(keypr); if (c == MVUP) return MVUP; } kb_setmapping(s, keypr); if (!c && (!(keypr & PLAYER_2) || inputdevs_player[0]==2)) return MVUP; } return MVDOWN; } #if JOYSTICK static int setkeymapping_js(int i, int keypr) { int b, b2; while (!(b = js_readbtn(i))) { if (inputdevs_fd[i+1] == -1) return STARTBTN; if (b = getkeypress_select(100, SINGLE_PL)) { if (b == ESC) { js_rmmapping(i, keypr); return MVDOWN; } return b; } sleep_msec(55); } b2 = js_readbtn(i); if (b > b2 && b2) b = b2; if (!key_is_valid(b, keypr)) return b; if (b == MVUP && keypr == MVUP && js_getbtnfor(i, MVUP) == MVUP) return MVUP; js_setmapping(i, b, keypr); return MVDOWN; } #endif int setkeymapping(int dev, int keypr) { ignore_dev = dev+1; #if JOYSTICK if (dev > 0) keypr = setkeymapping_js(dev-1, keypr); else #endif keypr = setkeymapping_keybd(keypr); kb_no_autorep = 0; ignore_dev = 0; return keypr; } static const char *getkeyfor_str_keybd(int keypr, int *c) { static unsigned char bytes[7]; const char *name; int n = kb_getkeyfor(keypr, bytes, 1); if (!n) return ""; name = kb_keyname(bytes, n); if (name) return name; bytes[n] = '\0'; if (n==1) { n = bytes[0]; if (n ==' ') strcpy((char *) bytes, "SPACE"); else if (n == DEL) strcpy((char *) bytes, "DEL"); else if (n < ' ') { if (n < 10) { *c = n; return NULL; } sprintf((char *) bytes, "%d", n); } } return (const char *) bytes; } const char *getkeyfor_str(int dev, int keypr) { const char *name; int c = 0; #if JOYSTICK if (dev) { c = js_getbtnfor(dev-1, keypr); name = js_btnname(c); } else #endif name = getkeyfor_str_keybd(keypr, &c); if (name) return name; if (c > 0 && c < 10) return input_chr9[c-1]; return ""; } static int dropsafe(int i) { int t = spawn_tm[i]; if (t && gettm(t)-t < DAS_DELAY) return 1; spawn_tm[i] = 0; return 0; } int processkey_ingame(int key, int flags) { static int discard_count; struct player *plr; int i = TWOPLAYER_MODE && key & PLAYER_2; int safe; switch (key & 0x7F) { case ESC: case '\b': game->state = 0; return -2; case 'q': exit(0); case STARTBTN: case 'p': if (flags & NO_PAUSE || !game_running || TWOPLAYER_MODE) break; i = pausegame(); textgfx_flags &= ~LOST_FOCUS; return i; } if (flags & DISCARD_MOVES) { if (++discard_count > 5) kb_flushinp(); return -1; } discard_count = 0; plr = game->player+i; safe = dropsafe(i); key &= 0x7F; if (!(flags & DISCARD_DROPS)) { switch (key) { case HARDDROP: if (socket_fd > -1 && !i) { sock_sendpiece(plr); if (harddrop(plr, safe) == -1) return -1; sock_sendbyte(HARDDROP); return 0; } return harddrop(plr, safe); case MVDOWN: if (!TWOPLAYER_MODE) return softdrop(softdrop_speed, safe); if (!movedown(plr, 1)) return 0; if (socket_fd > -1 && !i) sock_sendbyte(MVDOWN); return 1; } } switch (key) { case MVLEFT: moveleft(plr); break; case MVRIGHT: moveright(plr); break; case MVUP: rotate(plr, plr->rotationsys & ROT_CLOCKWISE); break; case A_BTN: rotate(plr, 1); break; case B_BTN: rotate(plr, 0); break; default: return -1; } if (socket_fd > -1 && !i) sock_sendbyte(key); upd_screen(1+i); return 1; } vitetris-0.58.0/src/input/input.h000066400000000000000000000025751344123051600167230ustar00rootroot00000000000000/* keypress values */ #define MVLEFT 1 #define MVRIGHT 2 #define MVUP 3 /* rotate */ #define MVDOWN 4 /* softdrop */ #define A_BTN 5 /* rotate clockwise */ #define B_BTN 6 /* rotate anticlockwise */ #define HARDDROP ' ' #define STARTBTN '\n' #define ESC '\033' #define DEL 0x7F #define BACKSPACE '\b' /* keypress bit flags */ #define IN_GAME 0x100 #define PLAYER_1 0x200 #define PLAYER_2 0x400 #define SINGLE_PL 0x800 #define DAS_INITIAL_DELAY 266 #define DAS_DELAY 100 extern const char input_chr9[9][4]; #if SOCKET #define NUM_INPUTDEVS 4 #elif JOYSTICK #define NUM_INPUTDEVS 3 #else #define NUM_INPUTDEVS 1 #endif #define socket_fd inputdevs_fd[3] extern int inputdevs_fd[4]; extern char inputdevs_player[4]; extern int num_joyst; extern int autorep_a_b_btns; extern int edit_mode; void init_inputdevs(); /* prepare for two-player game */ void initplayerinput(); /* returns NUM_INPUTDEV if no input is ready */ int inpselect_dev(int tm); /* wait msec < 1000 milliseconds for input on file descriptor */ int waitinput(int fd, unsigned msec); int getkeypress(int tm, int flags); int getkeypress_block(int flags); void spawn_discard_drops(int pl); int setkeymapping(int dev, int keypress); const char *getkeyfor_str(int dev, int keypress); /* processkey_ingame flags */ #define DISCARD_MOVES 1 #define DISCARD_DROPS 2 #define NO_PAUSE 8 int processkey_ingame(int keypress, int flags); vitetris-0.58.0/src/input/joylinux.c000066400000000000000000000135131344123051600174320ustar00rootroot00000000000000#include #include #include /* atexit */ #include #include #include #include #include #include #include "joystick.h" #include "input.h" #include "../timer.h" #include "../options.h" static struct js { uint32_t pressedbtns; short pressedbtns_tm[4]; short axis_tm[2]; char axis; } joysticks[2]; static int set_devname(int i, const char *devname) { union val v; v.p = devname; setoption(i==0 ? "js0" : "js1", "dev", v, 2); } int js_open(int i, const char *devname) { char s[16] = "/dev/"; int fd; if (inputdevs_fd[i+1] > 0) return 0; if (devname[0] != '/') { strncpy(s+5, devname, 10); devname = s; } fd = open(devname, O_RDONLY); if (fd == -1) { fprintf(stderr, "Could not open "); perror(devname); return 0; } inputdevs_fd[i+1] = fd; set_devname(i, devname); if (num_joyst <= i) num_joyst = i+1; return 1; } #ifndef JSIOCGBTNMAP #define getbtnmap(fd, js) #else static void getbtnmap(int fd, int i) { unsigned char n; uint16_t btnmap[KEY_MAX-BTN_MISC+1]; if (ioctl(fd, JSIOCGBUTTONS, &n) == -1 || ioctl(fd, JSIOCGBTNMAP, btnmap) == -1 || btnmap[0] == BTN_JOYSTICK) return; while (n) { switch (btnmap[--n]) { case BTN_A: js_setifnull(i, n+'0', A_BTN); break; case BTN_B: js_setifnull(i, n+'0', B_BTN); break; case BTN_START: js_setifnull(i, n+'0', STARTBTN); } } } #endif static int initjs(int fd, int i) { struct js_event e; char name[32] = ""; int v; if (read(fd, &e, sizeof(struct js_event)) < sizeof(struct js_event) || !(e.type & JS_EVENT_INIT) || ioctl(fd, JSIOCGVERSION, &v) == -1) return 0; inputdevs_fd[i+1] = fd; ioctl(fd, JSIOCGNAME(32), name); if (!strcmp(name, "Smartjoy Family Super Smartjoy")) js_setifnull(i, 11+'0', STARTBTN); getbtnmap(fd, i); js_default_buttons(i); return 1; } static int openjs(const char *devname, int i) { int fd = open(devname, O_RDONLY); if (fd > -1) { if (initjs(fd, i)) return 1; fprintf(stderr, "Error reading joystick device %s\n", devname); close(fd); } return 0; } static void try_openjs() { char devnames[24] = "/dev/js0\0/dev/input/js0"; char *p; int i = 0; while (1) { if (inputdevs_fd[i+1] == -1) { p = devnames; loop: if (openjs(p, i)) set_devname(i, p); else if (p == devnames) { p += 9; goto loop; } } if (i) break; i = 1; devnames[7] = '1'; devnames[22] = '1'; } } static void upd_num_joysticks() { if (inputdevs_fd[2] > -1) num_joyst = 2; else num_joyst = inputdevs_fd[1] > -1; } static void close_joysticks() { if (inputdevs_fd[1] > -1) close(inputdevs_fd[1]); if (inputdevs_fd[2] > -1) close(inputdevs_fd[2]); } void init_joysticks() { const char *js0, *js1; int *fd; js0 = getopt_str("js0", "dev"); js1 = getopt_str("js1", "dev"); if (js0 && inputdevs_fd[1] == -1) openjs(js0, 0); if (!js1) js1 = ""; else if (inputdevs_fd[2] == -1) openjs(js1, 1); try_openjs(); if (js0 && !strcmp(js0, js1)) { if (strchr(js0, '0')) { freeoptions("js1"); fd = inputdevs_fd+2; } else { freeoptions("js0"); fd = inputdevs_fd+1; } if (*fd > -1) { close(*fd); *fd = -1; } } upd_num_joysticks(); atexit(close_joysticks); } static void releasebtn(struct js *js, int b) { uint32_t btns = js->pressedbtns; short *tm = js->pressedbtns_tm; int i = 0; uint32_t mask; do { if (b == (btns & 0x7F)) { memmove(tm+i, tm+i+1, (3-i)*sizeof(short)); js->pressedbtns &= ~(0x7F << 8*i); if (!i) js->pressedbtns >>= 8; else { i *= 8; mask = ~0 << i; js->pressedbtns &= ~mask; js->pressedbtns |= (btns & ~0x7F) << i-8; } } i++; } while (btns >>= 8); } static int readjs_axis(struct js_event *e, struct js *js) { int axis = 0; int i = 0; int b = 0; switch (e->number) { case 1: i = 2; case 0: if (e->value) { axis = 1+(e->value > 0); if (js->axis & axis<axis_tm[i>>1] = gettm(0); b = MVLEFT+i+axis-1; } js->axis = (axis<axis & 12>>i); } return b; } static int readjs(int fd, struct js *js) { struct js_event e; int b; if (!waitinput(fd, 0) || read(fd, &e, sizeof(struct js_event)) < sizeof(struct js_event)) return 0; b = 0; if (e.type & JS_EVENT_BUTTON) { b = e.number+'0'; if (!e.value) { releasebtn(js, b); b = 0; } } else if (e.type & JS_EVENT_INIT) js->axis = 0; else if (e.type & JS_EVENT_AXIS) b = readjs_axis(&e, js); else { js->pressedbtns = 0; js->axis = 0; return -1; } return b ? b : readjs(fd, js); } int js_readbtn(int i) { int fd = inputdevs_fd[i+1]; int b = readjs(fd, joysticks+i); if (b > -1) return b; close(fd); inputdevs_fd[i+1] = -1; upd_num_joysticks(); return 0; } void js_pressbtn(int i, int b) { struct js *js = joysticks+i; short *tm = js->pressedbtns_tm; releasebtn(js, b); js->pressedbtns = b | js->pressedbtns << 8; tm[3] = tm[2]; tm[2] = tm[1]; tm[1] = tm[0]; tm[0] = gettm(0); } void js_releasebtn(int i, int b) { releasebtn(joysticks+i, b); } int js_pressed(int i) { struct js *js = joysticks+i; return js->axis || js->pressedbtns; } static int getautorep_btn(struct js *js, short **tm) { uint32_t btns = js->pressedbtns; int i = 0; do { if (test_autorep_tm(js->pressedbtns_tm+i)) { *tm = js->pressedbtns_tm+i; return btns & 0x7F; } i++; } while (btns >>= 8); return 0; } int js_autorep(int i, short **tm_ret) { struct js *js = joysticks+i; short *tm = js->axis_tm; int b = 0; if (js->axis & 3 && test_autorep_tm(tm)) b = MVLEFT+(js->axis & 3)-1; else if (js->axis & 12 && test_autorep_tm(tm+1)) { b = MVUP+(js->axis>>2)-1; tm++; } else if (js->pressedbtns) b = getautorep_btn(js, &tm); *tm_ret = tm; return b; } void js_reset_drop(int i) { struct js *js = joysticks+i; int t = gettm(0); js->axis_tm[1] = t; js->pressedbtns_tm[0] = t; js->pressedbtns &= 0x7F; } vitetris-0.58.0/src/input/joystick.c000066400000000000000000000104461344123051600174120ustar00rootroot00000000000000#include #include #include "joystick.h" #include "input.h" #include "../timer.h" int num_joyst = 0; int js_dead = 1; static struct btns { char menu_btns[7]; char ingame_btns[5]; } btns_joyst[2]; static const char *getbtn(int b, const char *p, int n) { while (n) { if (*p == b) return p; p++; n--; } return (char *) 0; } static char *getbtnfor(struct btns *js, int keypress) { char *btns; int i; if (keypress & IN_GAME) { btns = js->ingame_btns; if (keypress == (HARDDROP | IN_GAME)) i = 4; else i = (keypress & 7)-MVUP; } else { btns = js->menu_btns; if (keypress == STARTBTN) i = 6; else i = (keypress & 7)-MVLEFT; } return btns+i; } static int transl_btn(struct btns *js, int b, int flags) { const char *btns, *p; if (flags & IN_GAME) { btns = js->ingame_btns; if (p = getbtn(b, btns, 5)) return p==btns+4 ? HARDDROP : MVUP+p-btns; } btns = js->menu_btns; if (p = getbtn(b, btns, 7)) return p==btns+6 ? STARTBTN : MVLEFT+p-btns; return 0; } static int test_up_rotate(struct btns *js, int b, int keypr) { if (b==MVUP && keypr==MVUP) { b = *getbtnfor(js, MVUP | IN_GAME); if (b != MVUP) return 0; } return 1; } int js_getpress(int i, int flags) { struct btns *js = btns_joyst+i; int b, ret; int ingame = flags & IN_GAME; next: b = js_readbtn(i); if (!b) return 0; js_dead = 0; ret = transl_btn(js, b & 0x7F, flags); if (!ret) { if (ingame) goto next; return '.'; } if (b > MVDOWN && (ret <= MVRIGHT || !ingame && ret <= MVDOWN)) { js_pressbtn(i, b); js_releasebtn(i, *getbtnfor(js, (ret%4)%2 ? ret+1 : ret-1)); } else if (ingame) { if (!test_up_rotate(js, b, ret)) goto next; } else if (autorep_a_b_btns && b > MVDOWN && (ret == A_BTN || ret == B_BTN)) js_pressbtn(i, b); return ret; } static int js_getautorepeat(int i, int flags) { struct btns *js = btns_joyst+i; short *tm; int b = js_autorep(i, &tm); if (!b) return 0; i = transl_btn(js, b, flags); if (flags & IN_GAME) { if (i==MVDOWN) *tm -= DAS_DELAY/2; else if (i > MVRIGHT) return 0; } return i; } int getautorepeat(int flags) { int keypress = 0; int i = 0; while (i < num_joyst) { if (js_pressed(i)) { keypress = js_getautorepeat(i, flags); break; } i++; } i++; if (keypress && inputdevs_player[i] && !(flags & SINGLE_PL)) keypress |= inputdevs_player[i]==1 ? PLAYER_1 : PLAYER_2; return keypress; } int test_autorep_tm(short *tm) { int t = *tm; t = gettm(t)-t; if (t >= DAS_INITIAL_DELAY) { *tm = gettm(0)-t+DAS_DELAY+10000; return 1; } return 0; } static void rmbtn(struct btns *js, int b, int keypress) { int flags = keypress & IN_GAME; int old = transl_btn(js, b, flags); if (old && old != (keypress & 63)) { if (flags) { old |= flags; if (b != *getbtnfor(js, old)) return; } js_rmmapping(js!=btns_joyst, old); } } void js_setmapping(int i, int btn, int keypress) { struct btns *js = btns_joyst+i; char *b; keypress &= 63 | IN_GAME; rmbtn(js, btn, keypress); b = getbtnfor(js, keypress); if (*b && !(keypress & IN_GAME) && keypress >= MVUP) { keypress |= IN_GAME; if (*b == *getbtnfor(js, keypress)) js_setmapping(i, btn, keypress); } *b = btn; } int js_getbtnfor(int i, int keypress) { struct btns *js = btns_joyst+i; int b; keypress &= 63 | IN_GAME; b = *getbtnfor(js, keypress); if (b) return b; if ((keypress & 63) == HARDDROP || keypress == (MVUP | IN_GAME)) return 0; if (keypress & IN_GAME) { b = js_getbtnfor(i, keypress ^ IN_GAME); if (!b || getbtn(b, js->ingame_btns, 5)) return 0; return b; } return 0; } void js_rmmapping(int i, int keypress) { char *b = getbtnfor(btns_joyst+i, keypress & (63 | IN_GAME)); if (*b) *b = 0; } void js_setifnull(int i, int btn, int keypress) { if (!js_getbtnfor(i, keypress)) js_setmapping(i, btn, keypress); } void js_default_buttons(int i) { char *btns = btns_joyst[i].menu_btns; char defaults[6] = {MVLEFT, MVRIGHT, MVUP, MVDOWN, '0', '1'}; if (memchr(btns, '0', 6)) defaults[4] = 0; if (memchr(btns, '1', 6)) defaults[5] = 0; for (i=0; i < 6; i++) if (!btns[i]) btns[i] = defaults[i]; } const char *js_btnname(int btn) { static char name[4]; if (btn < '0') return (const char *) 0; btn -= '0'; if (btn < 26) { name[0] = btn+'A'; name[1] = '\0'; } else sprintf(name, "%d", btn); return name; } vitetris-0.58.0/src/input/joystick.h000066400000000000000000000016611344123051600174160ustar00rootroot00000000000000/* true until we receive any events */ extern int js_dead; /* prints error message if open fails */ int js_open(int i, const char *devname); void init_joysticks(); /* reads a button press */ int js_readbtn(int i); /* get translated keypress */ int js_getpress(int i, int flags); int getautorepeat(int flags); int test_autorep_tm(short *tm); /* set autorepeat timer for btn (not axis) */ void js_pressbtn(int i, int btn); void js_releasebtn(int i, int btn); int js_pressed(int i); /* returns button press to repeat */ int js_autorep(int i, short **tm_ret); /* reset autorepeat timer for softdrop */ void js_reset_drop(int i); void js_setmapping(int i, int btn, int keypress); int js_getbtnfor(int i, int keypress); void js_rmmapping(int i, int keypress); /* set mapping if not set */ void js_setifnull(int i, int btn, int keypress); /* set default mappings if null */ void js_default_buttons(int i); const char *js_btnname(int btn); vitetris-0.58.0/src/input/keyboard.c000066400000000000000000000125401344123051600173500ustar00rootroot00000000000000#include #include "keyboard.h" #include "input.h" #include "escseq.h" int kb_no_autorep = 0; static struct keys { unsigned short menu_keys[6]; unsigned short ingame_keys[5]; } keys_singlepl; #ifdef TWOPLAYER static struct keys keys_1p, keys_2p; #endif static int transl_chr_ingame(unsigned c, unsigned short *keys) { int i = 0; keys += keys_singlepl.ingame_keys - keys_singlepl.menu_keys; while (i < 5) { if (keys[i] == c) return i==4 ? HARDDROP : MVUP+i; i++; } return 0; } static int transl_chr(unsigned c, int k) { unsigned short *keys; int i; #ifdef TWOPLAYER if (k & PLAYER_1) keys = keys_1p.menu_keys; else if (k & PLAYER_2) keys = keys_2p.menu_keys; else if (!(k & SINGLE_PL)) { if (i = transl_chr(c, k | PLAYER_1)) return i | PLAYER_1; if (i = transl_chr(c, k | PLAYER_2)) return i | PLAYER_2; return 0; } else #endif keys = keys_singlepl.menu_keys; if ((k & IN_GAME) && (k = transl_chr_ingame(c, keys))) return k; for (i = 0; i < 6; i++) if (keys[i] == c) return MVLEFT+i; return 0; } static int transl_input(const unsigned char *input, int flags) { unsigned c = *input; #ifdef TWOPLAYER if (!(flags & (PLAYER_1 | PLAYER_2))) { if (inputdevs_player[0] == 1) flags |= PLAYER_1 | SINGLE_PL; if (inputdevs_player[0] == 2) flags |= PLAYER_2 | SINGLE_PL; } #endif #ifdef ESCSEQ if (c == ESC) return transl_escseq((const char *) input+1, flags); #else c |= input[1] << 8; #endif return transl_chr(c, flags); } int kb_getpress(int flags) { unsigned char s[5] = ""; unsigned c; if (!kb_readkey(s)) return 0; if (c = transl_input(s, flags)) return c; if (!s[1]) c = s[0]; else if (flags & IN_GAME) c = ESC+1; else c = kb_toascii(s); if (!(flags & IN_GAME) || c <= MVDOWN #ifdef TWOPLAYER && (flags & SINGLE_PL || inputdevs_player[0] || !keys_1p.menu_keys[c-MVLEFT]) #endif ) return c; if (strchr("\033\b \npq", c)) return c; return kb_getpress(flags); } static unsigned short *getchrfor(int keypress) { unsigned short *keys; int i; #ifdef TWOPLAYER if (keypress & PLAYER_1) keys = keys_1p.menu_keys; else if (keypress & PLAYER_2) keys = keys_2p.menu_keys; else #endif keys = keys_singlepl.menu_keys; if (keypress & IN_GAME) { keys += keys_singlepl.ingame_keys - keys_singlepl.menu_keys; if ((keypress & 63) == HARDDROP) i = 4; else i = (keypress & 7)-MVUP; } else i = (keypress & 7)-MVLEFT; return keys+i; } static int key_equals(int keypr, const unsigned char *input) { unsigned c = *input; #if ESCSEQ if (c == ESC) return !strncmp((const char *) input+1, getescseq_str(keypr), 3); #else c |= input[1] << 8; #endif return c == *getchrfor(keypr); } static int transl_strict(const unsigned char *input, int flags) { int k = transl_input(input, flags | SINGLE_PL); if (flags & IN_GAME && !key_equals(k | flags, input)) k = 0; return k; } static void rmkey(const unsigned char *input, int keypr) { int flags = keypr & (IN_GAME | PLAYER_1 | PLAYER_2); int old = transl_strict(input, flags); if (old && old != (keypr & 63)) kb_rmmapping(old | flags); #ifdef TWOPLAYER if (!(flags & (PLAYER_1 | PLAYER_2))) return; flags ^= PLAYER_1 | PLAYER_2; if (old = transl_strict(input, flags)) kb_rmmapping(old | flags); flags ^= IN_GAME; if (old = transl_strict(input, flags)) kb_rmmapping(old | flags); #endif } static int ingame_key_equals(int keypr, unsigned c) { const char *s; if (keypr & IN_GAME || (keypr & 7) < MVUP) return 0; #ifdef ESCSEQ if (!c) { s = getescseq_str(keypr); return *s && !strncmp(s, getescseq_str(keypr | IN_GAME), 3); } #endif return c && c == *getchrfor(keypr | IN_GAME); } void kb_setmapping(const unsigned char *input, int keypr) { unsigned short *c = getchrfor(keypr); rmkey(input, keypr); if (ingame_key_equals(keypr, *c)) kb_setmapping(input, keypr | IN_GAME); #ifdef ESCSEQ if (!input[0]) return; if (input[0] == ESC) { *c = 0; mapescseq((const char *) input+1, keypr); return; } if (*getescseq_str(keypr)) rmescseq(keypr); #endif *c = input[0]; #ifndef ESCSEQ *c |= input[1] << 8; #endif } static int test_fallback(int keypr, const unsigned char *input) { int flags = keypr & IN_GAME; int k = keypr & 63; #ifdef TWOPLAYER int pl = keypr & (PLAYER_1 | PLAYER_2); if (!pl) flags |= SINGLE_PL; #endif if ((!(keypr & IN_GAME) || k==HARDDROP) && (k==A_BTN || k==B_BTN #ifdef TWOPLAYER || pl==PLAYER_2 && inputdevs_player[0] != 2 #endif )) return 0; keypr = transl_input(input, flags); return !keypr || #ifdef TWOPLAYER pl == (keypr & (PLAYER_1 | PLAYER_2)) && #endif k == (keypr & 63); } int kb_getkeyfor(int keypr, unsigned char *dest, int fallback) { unsigned c = *getchrfor(keypr); #ifdef ESCSEQ const char *s; if (c) { *dest = c; return 1; } s = getescseq_str(keypr); if (*s) { dest[0] = ESC; strncpy((char *) dest+1, s, 3); dest[4] = '\0'; return strlen((char *) dest); } #else if (c) { *dest = c & 0xFF; if (c >>= 8) { dest[1] = c; return 2; } return 1; } #endif if (!fallback) return 0; *dest = keypr; dest[1] = 0; c = 1; if (keypr & IN_GAME && *dest != HARDDROP) c = kb_getkeyfor(keypr ^ IN_GAME, dest, 1); if (c && !test_fallback(keypr, dest)) c = 0; return c; } int kb_getchrfor(int keypress) { return *getchrfor(keypress); } void kb_rmmapping(int keypress) { unsigned short *c = getchrfor(keypress); *c = 0; #ifdef ESCSEQ rmescseq(keypress); #endif } vitetris-0.58.0/src/input/keyboard.h000066400000000000000000000012331344123051600173520ustar00rootroot00000000000000extern int kb_no_autorep; void init_keybd(); /* reads a key press into dest, returns number of bytes read */ int kb_readkey(unsigned char *dest); int kb_getpress(int flags); int kb_toascii(const unsigned char *key); /* reset autorepeat timer for softdrop */ void kb_reset_drop(int pl); /* throw away typeahead */ void kb_flushinp(); void kb_setmapping(const unsigned char *input, int keypress); /* returns number of chars copied into dest */ int kb_getkeyfor(int keypress, unsigned char *dest, int fallback); int kb_getchrfor(int keypress); void kb_rmmapping(int keypress); /* returns key name or null */ const char *kb_keyname(unsigned char *key, int n); vitetris-0.58.0/src/input/playerin.c000066400000000000000000000017061344123051600173750ustar00rootroot00000000000000#include #include "input.h" #include "joystick.h" /* js_dead */ #include "../options.h" static int getdev(const char *str) { if (str) { if (!strcmp(str, "js0")) return inputdevs_fd[1] > -1; if (!strcmp(str, "js1") && inputdevs_fd[2] > -1) return 2; } return 0; } static void setpl2js() { const char *s = "js0"; union val v; if (inputdevs_fd[1] < 0) s = "js1"; strcpy(v.str, s); setoption("player2", "input", v, 1); inputdevs_player[s[2]-'0'+1] = 2; } void initplayerinput() { int devs[2]; if (!num_joyst) { inputdevs_player[0] = 0; return; } inputdevs_player[0] = 1; devs[0] = getdev(getopt_str("player1", "input")); devs[1] = getdev(getopt_str("player2", "input")); if (devs[0] != devs[1]) { inputdevs_player[devs[0]] = 1; inputdevs_player[devs[1]] = 2; } else if (devs[0]) { unsetoption("player1", "input"); inputdevs_player[devs[0]] = 2; } else if (js_dead) inputdevs_player[0] = 0; else setpl2js(); } vitetris-0.58.0/src/input/playerin.h000066400000000000000000000003001344123051600173670ustar00rootroot00000000000000/* Functions to initialize player input. */ /* returns 1 for "js0" if active, 2 for "js1" if active 0 otherwise */ int getinputdev(const char *str); void initplayerinput(int *devs); vitetris-0.58.0/src/input/select.c000066400000000000000000000011731344123051600170270ustar00rootroot00000000000000#include "select.h" #include #include /* perror */ #include /* exit */ #include "input.h" #include "../textgfx/textgfx.h" int inpselect(int n, fd_set *set, struct timeval *tmout) { n = select(n, set, NULL, NULL, tmout); if (n == -1 && errno != EINTR) { textgfx_end(); perror("Error waiting for input"); exit(1); } return n; } int waitinput(int fd, unsigned ms) { fd_set set; struct timeval tmv; int ret; if (fd < 0) return 0; do { FD_ZERO(&set); FD_SET(fd, &set); tmv.tv_sec = 0; tmv.tv_usec = 1000*ms; ret = inpselect(fd+1, &set, &tmv); } while (ret == -1); return ret; } vitetris-0.58.0/src/input/select.h000066400000000000000000000004041344123051600170300ustar00rootroot00000000000000#include "../config.h" #if HAVE_SYS_SELECT_H #include #elif __DJGPP__ #include #include #else #include #include #include #endif int inpselect(int n, fd_set *set, struct timeval *tmout); vitetris-0.58.0/src/input/termin.h000066400000000000000000000001761344123051600170550ustar00rootroot00000000000000extern char unreadchr; void set_input_mode(); void restore_input_mode(); int readchr(); int waitinput_stdin(unsigned msec); vitetris-0.58.0/src/int32t.h000066400000000000000000000007701344123051600155430ustar00rootroot00000000000000#ifndef int32t_h #define int32t_h #include "config.h" #if HAVE_STDINT_H #include #elif HAVE_INTTYPES_H && HAVE_UINT_LEAST32_T #include #elif HAVE_SYS_TYPES_H && HAVE_U_INT32_T #include typedef int32_t int_least32_t; typedef uint32_t uint_least32_t; #elif __TURBOC__ || __PACIFIC__ typedef long int_least32_t; typedef unsigned long uint_least32_t; #elif !defined(_STDINT_H) typedef int int_least32_t; typedef unsigned uint_least32_t; #endif #endif /* !int32t_h */ vitetris-0.58.0/src/lang.c000066400000000000000000000020761344123051600153350ustar00rootroot00000000000000#include #include #include #include "lang.h" int lang = SPELL_GB; static int islatin1(const char *s) { while (*s) { if (*s == '.') break; s++; } if (*s != '.') return 1; s++; if (strncmp(s, "ISO", 3) && strncmp(s, "iso", 3)) return 0; s += 3; if (*s == '-') s++; if (strncmp(s, "8859", 4)) return 0; s += 4; if (*s == '-') s++; return *s == '1' && (!s[1] || s[1] == '5'); } void getlang() { const char *s = getenv("LANG"); if (!s) return; if (!strncmp(s, "en_US", 5) || !strncmp(s, "en_us", 5)) lang = SPELL_US; else lang = SPELL_GB; if (islatin1(s)) lang |= LATIN1; } void spellword(char *s) { int c; if (lang & SPELL_GB) return; c = tolower(s[0]); if (c=='a') { if (!strcmp(s, "acw")) s[0] = 'c'; else if (!strncmp(s+1, "nticlockw", 9)) { memmove(s+7, s+4, strlen(s+3)); memcpy(s, "counter", 7); } else if (!strcmp(s+1, "lternative")) { s[8] = 'e'; s[9] = '\0'; } } else if (c=='c' && !strncmp(s+1, "olour", 5)) { s[4] = s[5]; s[5] = s[6]; if (s[5]) s[6] = '\0'; } } vitetris-0.58.0/src/lang.h000066400000000000000000000001661344123051600153400ustar00rootroot00000000000000#define SPELL_GB 1 #define SPELL_US 2 #define LATIN1 4 extern int lang; void getlang(); void spellword(char *word); vitetris-0.58.0/src/main.c000066400000000000000000000055141344123051600153400ustar00rootroot00000000000000#include #include #include #include #ifdef ALLEGRO #include #include "config.h" #include #include "textgfx/alleg.h" #else #define END_OF_MAIN() #endif #include "timer.h" #include "cfgfile.h" #include "options.h" #include "lang.h" #include "focus.h" #include "textgfx/textgfx.h" #include "input/input.h" #include "game/tetris.h" #include "game/game.h" #include "menu/menuext.h" #include "netw/sock.h" #ifdef TTY_SOCKET #define mk_invitfile() mkinvitfile() #define rm_invitfile() rminvitfile() #else #define mk_invitfile() #define rm_invitfile() #endif /* startup menu items */ #ifdef INET #define OPTIONS 6 #define HIGHSCORES 7 #else #define OPTIONS 5 #define HIGHSCORES 6 #endif void proc_args(char **args, int n); static void setupgame(int i) { allocgame(i & 2); initgame(); #if !NO_MENU if (!in_menu) goto skipmenu; while (gamemenu()) { in_menu = 0; rm_invitfile(); skipmenu: #endif writeconfig(); do textgfx_entergame(); while (startgame()); #if !NO_MENU clearwin(0); in_menu = 1; textgfx_entermenu(); readoptions(); } inputdevs_player[0] = 0; # ifdef SOCKET rmsocket(); mk_invitfile(); # endif #endif game = NULL; } static void startup(int i) { #if XLIB in_xterm_init(); #endif textgfx_init(); atexit(textgfx_end); init_inputdevs(); #if TERM_RESIZING enable_term_resizing(); #endif if (!bgdot) bgdot = default_bgdot(); if (in_menu) textgfx_entermenu(); #if !TWOPLAYER setupgame(1); #else if (i) goto setup; i = getopt_int("", "mode"); if (i & MODE_NETWORK) i = 3; else i = 2-!(i & MODE_2PLAYER); # if NO_MENU setup: setupgame(i); # else if (!in_menu) goto setup; mk_invitfile(); while (1) { i = startupmenu(i); if (!i) break; # ifdef INET if (i==3 && !netplaymenu()) continue; # endif if (i <= 3) { setup: setupgame(i); # ifdef INET if (i==3 && playerlist_n > 0 && netplaymenu()) goto setup; # endif } if (i==OPTIONS) optionsmenu(); if (i==HIGHSCORES) hiscorelist(); } # endif /* !NO_MENU */ #endif /* TWOPLAYER */ textgfx_end(); } static void cleanup() { timer_end(); freeoptions(""); #if !NO_MENU rm_invitfile(); #endif #ifdef SOCKET sock_flags &= ~CONNECTED; rmsocket(); #endif #if ALLEGRO && WIN32 && !ALLEGRO_USE_CONSOLE fclose(stdout); delete_file("stdout.tmp"); #endif } static void finish(int sig) { exit(0); } int main(int argc, char **argv) { setcfgfilename(argv[0]); readoptions(); timer_init(); atexit(cleanup); #if UNIX signal(SIGINT, finish); #endif gettermsize(); getlang(); if (argc > 1) { #if ALLEGRO && WIN32 && !ALLEGRO_USE_CONSOLE freopen("stdout.tmp", "w", stdout); #endif proc_args(argv+1, argc-1); } gettermoptions(); #ifdef SOCKET startup(socket_fd>0 ? 2+is_inet() : 0); #else startup(0); #endif #if !NO_MENU writeconfig_message(); #endif return 0; } END_OF_MAIN() vitetris-0.58.0/src/menu/000077500000000000000000000000001344123051600152075ustar00rootroot00000000000000vitetris-0.58.0/src/menu/Makefile000066400000000000000000000060521344123051600166520ustar00rootroot00000000000000include ../src-conf.mk OBJS = menucore.o dropdown.o inputset.o inputdev.o \ gamemenu.o gm_2p.o gm_sock.o \ hslist.o gameover.o EXT_OBJS = startup.o invit.o netplay.o \ optsmenu.o blockstyle.o men_$(BACKEND).o HEADERS = menu.h ../input/input.h ../textgfx/textgfx.h all: menu.a $(menuext_lib) menu.a: $(OBJS) ar rs menu.a $(OBJS) menuext.a: $(EXT_OBJS) rm -f menuext.a ar rcs menuext.a $(EXT_OBJS) menucore.o: menucore.c $(HEADERS) ../src-conf.mk $(CC) $(CCFLAGS) $(DNO_MENU) -c menucore.c dropdown.o: dropdown.c $(HEADERS) ../draw/draw.h $(CC) $(CCFLAGS) -c dropdown.c inputset.o: inputset.c $(HEADERS) internal.h \ ../draw/draw.h ../lang.h ../src-conf.mk $(CC) $(CCFLAGS) $(DTWOPLAYER) $(DJOYSTICK) $(DNO_MENU) -c inputset.c inputdev.o: inputdev.c $(HEADERS) internal.h ../options.h ../src-conf.mk $(CC) $(CCFLAGS) $(DTWOPLAYER) $(DNO_MENU) -c inputdev.c gamemenu.o: gamemenu.c menu.h internal.h ../input/input.h ../game/tetris.h \ ../lang.h ../options.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(DTWOPLAYER) $(DJOYSTICK) $(DSOCKET) -c gamemenu.c gm_2p.o: gm_2p.c $(HEADERS) internal.h ../draw/draw.h $(CC) $(CCFLAGS) -c gm_2p.c gm_sock.o: gm_sock.c $(HEADERS) internal.h ../netw/sock.h ../draw/draw.h \ ../game/tetris.h ../game/game.h $(CC) $(CCFLAGS) -I.. -c gm_sock.c hslist.o: hslist.c $(HEADERS) ../hiscore.h $(CC) $(CCFLAGS) -I.. -c hslist.c gameover.o: gameover.c $(HEADERS) ../hiscore.h ../draw/draw.h ../game/tetris.h $(CC) $(CCFLAGS) -I.. -c gameover.c startup.o: startup.c menu.h menuext.h ../options.h ../game/tetris.h \ ../src-conf.mk $(CC) $(CCFLAGS) -I.. -c startup.c $(DINET) invit.o: invit.c $(HEADERS) menuext.h ../draw/draw.h ../netw/sock.h $(CC) $(CCFLAGS) -c invit.c netplay.o: netplay.c $(HEADERS) menuext.h ../netw/sock.h ../options.h $(CC) $(CCFLAGS) -c netplay.c optsmenu.o: optsmenu.c menu.h menuext.h ../input/input.h ../textgfx/textgfx.h \ ../draw/draw.h ../options.h ../lang.h ../src-conf.mk $(CC) $(CCFLAGS) $(DTWOPLAYER) $(DNO_BLOCKSTYLES) -c optsmenu.c blockstyle.o: blockstyle.c menu.h menuext.h ../textgfx/textgfx.h ../options.h $(CC) $(CCFLAGS) -c blockstyle.c men_ansi.o: men_ansi.c menu.h menuext.h ../draw/draw.h ../game/tetris.h \ ../textgfx/textgfx.h ../textgfx/ansivt.h ../lang.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(DTWOPLAYER) $(DTTY_SOCKET) $(DINET) $(DNO_BLOCKSTYLES) -c men_ansi.c men_curses.o: men_curses.c menu.h menuext.h ../draw/draw.h ../game/tetris.h \ ../textgfx/textgfx.h ../textgfx/curs.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(CURSES_INC) $(DTWOPLAYER) $(DINET) $(DTTY_SOCKET) $(DNO_BLOCKSTYLES) -c men_curses.c men_allegro.o: men_allegro.c menu.h menuext.h ../draw/draw.h ../game/tetris.h \ ../textgfx/textgfx.h ../input/input.h ../options.h \ ../config.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(DTWOPLAYER) $(DTTY_SOCKET) $(DINET) $(DNO_BLOCKSTYLES) -c men_allegro.c clean: rm -f menu.a menuext.a $(OBJS) rm -f $(EXT_OBJS) rm -f men_ansi.o men_curses.o men_allegro.o rm -f block~wv.o men_c~9i.o men_a~ol.o .PHONY: all clean vitetris-0.58.0/src/menu/blockstyle.c000066400000000000000000000051731344123051600175340ustar00rootroot00000000000000#include #include "menu.h" #include "menuext.h" #include "../textgfx/textgfx.h" #include "../options.h" int getblockstyle() { if (_TT_BLOCKS) return 1; if (_TT_BLOCKS_BG) return 2; if (textgfx_flags & BLACK_BRACKETS && block_chars[0]=='[' && block_chars[1]==']') return 3; if (!getopt_int("term", "block")) return 0; return 4; } static void setblockstyle(int i, int c) { union val v; int tp = 0; if (_TT_BLOCKS && bgdot==' ') { bgdot = default_bgdot(); unsetoption("term", "bgdot"); } textgfx_flags &= ~(TT_BLOCKS | TT_BLOCKS_BG); if (!c) { textgfx_flags &= ~BLACK_BRACKETS; c = 'X'; } v.integ = 0; switch (i) { case 0: unsetoption("term", "block"); reset_block_chars(); return; case 1: textgfx_flags |= TT_BLOCKS; bgdot = ' '; setoption("term", "bgdot", v, 1); v.integ = -1; break; case 2: textgfx_flags |= TT_BLOCKS_BG; v.integ = -2; break; case 3: textgfx_flags |= BLACK_BRACKETS; block_chars[0] = '['; block_chars[1] = ']'; strcpy(v.str, "[]b"); tp = 1; break; case 4: block_chars[0] = c; block_chars[1] = ' '; v.str[0] = c; if (textgfx_flags & BLACK_BRACKETS) { v.str[1] = ' '; v.str[2] = 'b'; } tp = 1; } setoption("term", "block", v, tp); } static void save_custom_blockstyle() { union val v; v.integ = 0; v.str[0] = block_chars[0]; if (v.str[0]==' ') v.str[0]--; v.str[1] = block_chars[1]; if (block_chars[0] & 0x100) v.str[2] = 'a'; else if (textgfx_flags & BLACK_BRACKETS) v.str[2] = 'b'; else v.str[2] = '_'; setoption("term", "block", v, 1); } static void edit_custom_blockstyle(int i, int c) { static int pos; if (i != 4) { setblockstyle(4, c); pos = 1; return; } if (!pos || pos == 2 && c != 'a') { block_chars[0] = c; block_chars[1] = ' '; pos = 1; } else if (pos == 1) { block_chars[1] = c; pos = (textgfx_flags & (ASCII | BLACK_BRACKETS)) ? 0 : 2; } else { block_chars[0] |= 0x100; block_chars[1] |= 0x100; pos = 0; } save_custom_blockstyle(); } int select_blockstyle(int k) { const char *styles[5] = {"default","tt","tt-bg","brackets","custom"}; const char **items = styles; int n = 5; int i = getblockstyle(); int j; if (isprintable(k)) { edit_custom_blockstyle(i, k); return 3; } if ((textgfx_flags & (WHITE_BG | MONOCHROME)) == WHITE_BG) { items[1] = items[0]; items++; n--; if (i) i--; } j = i; k = selectitem(items, n, &i, k); if (i != j) { if (i && n==4) i++; setblockstyle(i, 0); return 3; } if (k != 1) return k; if (textgfx_flags & (TT_BLOCKS | TT_BLOCKS_BG)) printstr(" "); else { putch(block_chars[0]); putch(block_chars[1]); } return 1; } vitetris-0.58.0/src/menu/dropdown.c000066400000000000000000000037521344123051600172160ustar00rootroot00000000000000#include /* exit */ #include #include "menu.h" #include "../input/input.h" #include "../textgfx/textgfx.h" #include "../draw/draw.h" static int getdropdownwidth(const char **items, int n) { int w = strlen(items[0]); int i = 1; while (i < n) { if (w < strlen(items[i])) w = strlen(items[i]); i++; } return w; } static void printdropdownitem(const char *name, int sel, int w) { if (sel) { while (name[0]==' ' && name[1]==' ') { putch(' '); name++; w--; } setattr_normal(); } printstr(name); if (strlen(name) < w) putch(' '); if (sel) setattr_standout(); } int dropdownlist(const char **items, int n, int i, int x, int y) { int w = getdropdownwidth(items, n); int j; while (is_outside_screen(0, y+n+1)) y--; setattr_standout(); drawbox(x, y, w+2, n+2, NULL); x++; y++; setcurs(x, y); for (j = 0; j < n; j++) { printdropdownitem(items[j], i==j, w); newln(x); } while (1) { setcurs(x-1, y+i); refreshwin(-1); switch (getkeypress_block(SINGLE_PL) & 0xFF) { case STARTBTN: case A_BTN: goto out; case 'q': exit(0); case MVUP: if (!i) continue; j = -1; break; case '\t': if (i == n-1) { j = -i; break; } case MVDOWN: if (i < n-1) { j = 1; break; } case MVRIGHT: continue; default: i = -1; goto out; } setcurs(x, y+i); printdropdownitem(items[i], 0, w); i += j; setcurs(x, y+i); printdropdownitem(items[i], 1, w); } out: clearbox(x-1, y-1, w+2, n+2); return i+1; } int selectitem(const char **items, int n, int *i, int k) { int x, y; switch (k) { case 0: break; case MVLEFT: if (*i) *i -= 1; break; case MVRIGHT: if (*i < n-1) *i += 1; break; case STARTBTN: case A_BTN: get_xy(&x, &y); n = dropdownlist(items, n, *i, x, y); if (n) *i = n-1; setcurs(x, y); return 3; default: return 0; } putch('['); printstr(items[*i]); n = getdropdownwidth(items, n) - strlen(items[*i]); putnchars(' ', n); printstr("] "); return 1; } vitetris-0.58.0/src/menu/gamemenu.c000066400000000000000000000063401344123051600171540ustar00rootroot00000000000000#include "menu.h" #include "internal.h" #include "../input/input.h" #include "../game/tetris.h" #include "../lang.h" #include "../options.h" static int gm_level(int k, int *pos) { struct player *p = game->player+(player_==2); int i; if (k==MVLEFT) k = -1; else if (k==MVRIGHT) k = 1; else if (k >= '0' && k <= '9') { p->startlevel = 0; k -= '0'; } else if (k) return 0; i = p->startlevel+k; if (i >= 0 && i < 10) { p->startlevel = i; printmenuitem_options("0 1 2 3 4 5 6 7 8 9", i); } return 1; } static int gm_height(int k, int *pos) { struct player *p = game->player+(player_==2); int i; if (k==MVLEFT) k = -1; else if (k==MVRIGHT) k = 1; else if (k >= '0' && k <= '5') { p->height = 0; k -= '0'; } else if (k) return 0; i = p->height+k; if (i >= 0 && i <= 5) { p->height = i; printmenuitem_options("0 1 2 3 4 5", i); } return 1; } static int gm_rotate(int k, int *pos) { char s[25] = "clockwise anticlockw."; struct player *p = game->player+(player_==2); spellword(s+10); if (k==MVLEFT) p->rotationsys |= ROT_CLOCKWISE; else if (k==MVRIGHT) p->rotationsys &= ~ROT_CLOCKWISE; else if (k) return 0; printmenuitem_options(s, !(p->rotationsys & ROT_CLOCKWISE)); return 1; } static int gm_orient(int k, int *pos) { struct player *p = game->player+(player_==2); if (k==MVLEFT) p->rotationsys |= ROT_LEFTHAND; else if (k==MVRIGHT) p->rotationsys &= ~ROT_LEFTHAND; else if (k) return 0; printmenuitem_options("left right -handed", !(p->rotationsys & ROT_LEFTHAND)); return 1; } static int gm_softdrop(int k, int *pos) { const char steps[5] = {1, 2, 3, 5, 20}; int i; for (i = 0; i < 4; i++) if (steps[i] >= softdrop_speed) break; if (k==MVLEFT) { if (!i) return 1; i--; } else if (k==MVRIGHT) { if (i==4) return 1; i++; } else if (k) return 0; if (k) softdrop_speed = steps[i]; printmenuitem_options("1 2 3 5 20", i); return 1; } int game_menu(int i, int x, int y) { const char *menu[GAMEMENU_LENGTH] = { "Level", "Height", "-", "Input Setup", "Rotate", "Rotation Sys", "Softdrop Speed" #ifndef TWOPLAYER ,"-", "Options", "Highscores" #endif }; menuhandler handlers[GAMEMENU_LENGTH] = { gm_level, gm_height, NULL, inputsetup_menuitem, gm_rotate, gm_orient, gm_softdrop #ifndef TWOPLAYER ,NULL, rarrow_menuitem, rarrow_menuitem #endif }; struct player *p = &player1; const char *s = ""; union val v; #ifdef TWOPLAYER player_ = 0; #endif if (socket_fd > -1) i = gamemenu_socket(menu, i, x, y, handlers); else if (TWOPLAYER_MODE) { if (game->mode & MODE_NETWORK) return 0; i = gamemenu_2p(menu, x, y, handlers); } else i = openmenu(menu, GAMEMENU_LENGTH, i, x, y, handlers); if (i==4) return 4; if (!i) return 0; #ifndef TWOPLAYER if (i >= GAMEMENU_LENGTH-2) return i; #endif if (TWOPLAYER_MODE && socket_fd == -1) s = "player1"; while (1) { v.integ = p->startlevel; setoption(s, "level", v, 0); v.integ = p->height; setoption(s, "height", v, 0); v.integ = p->rotationsys; setoption(s, "rotate", v, 0); if (!TWOPLAYER_MODE) { v.integ = softdrop_speed; setoption("", "softdrop", v, 0); break; } if (p == &player2 || socket_fd > -1) break; p = &player2; s = "player2"; } return 1; } vitetris-0.58.0/src/menu/gameover.c000066400000000000000000000106441344123051600171650ustar00rootroot00000000000000#include #include #include #include "menu.h" #include "../input/input.h" #include "../textgfx/textgfx.h" #include "../hiscore.h" #include "../draw/draw.h" #include "../game/tetris.h" void show_hiscorelist5(int x, int y, int i) { char s[20]; const struct hiscore *hs, *end; int n; if (!hiscores[0].score && !readhiscores(NULL)) return; setcurs(x, y); hs = hiscores; i -= 5; if (i < 0) i = 0; else hs += i; end = hs+5; while (hs->score && hs != end) { n = sprintf(s, "%2d. %s", i+1, gethiscorename(i, s+12)); memset(s+n, ' ', 12-n); sprintf(s+12, "%7ld", (long) hs->score); printstr(s); newln(x); hs++; i++; } } static void printsavebutton(int sel) { if (_MONOCHROME) { if (sel) setattr_standout(); else setattr_bold(); } else if (sel) { setcolorpair(YELLOW_ON_GREEN); } else { setcolorpair(4); putch('['); setcolorpair(YELLOW_ON_BLUE); printstr(" Save "); setcolorpair(4); putch(']'); goto out; } printstr("[ Save ]"); out: setattr_normal(); } static int hiscore_editname(char *name, int pos, int k) { const char chars[18] = "Z.!?-0123456789 A"; const char lat1_chars[5] = "ÅÄÖÜ"; const char lat1_chars_small[5] = "åäöü"; int c, i; char *p; if (k == MVLEFT && pos) pos--; else if (k == '\b' && pos) { pos--; memmove(name+pos, name+pos+1, 6-pos); name[6] = ' '; } else if (pos == 7) return pos; else if (k == MVRIGHT) pos++; else if (k == '\t') pos = 7; else if (k == 0x7F) { memmove(name+pos, name+pos+1, 6-pos); name[6] = ' '; } else { c = 0; i = 0; if (k >= 'A' && k <= 'Z' || strchr(chars, k) || strchr(lat1_chars, k)) c = k; else if (k >= 'a' && k <= 'z') c = k-32; else if (p = strchr(lat1_chars_small, k)) c = lat1_chars[p-lat1_chars_small]; else if (k == MVUP || k == A_BTN || k == B_BTN) { c = name[pos]; i = (k==B_BTN) ? -1 : 1; if (c > 'A'-(i>0) && c < 'Z'+(i<0)) c += i; else c = *(strchr(chars, c)+i); } if (c) { name[pos] = c; if (!i) pos++; } } return pos; } static int hiscore_entername_menu(char *name, const char **menu, int x, int y) { int pos = 0; int i = 0; int k; while (1) { drawmenu(menu, 2, i-2, x, y+2, NULL); textbox: setcurs(x, y); printtextbox(name, pos); movefwd(3); printsavebutton(!i && pos==7); if (!i) x += pos; setcurs(x, y+i); refreshwin(-1); autorep_a_b_btns = 1; k = getkeypress_block(SINGLE_PL) & 0xFF; autorep_a_b_btns = 0; if (k == ESC) return 0; if (!i) { x -= pos; switch (k) { case STARTBTN: return 1; case '\t': if (pos < 7) break; case MVDOWN: i = 2; continue; } pos = hiscore_editname(name, pos, k); goto textbox; } switch (k) { case STARTBTN: case A_BTN: if (i==2) return 2; case 'q': exit(0); case MVUP: i = i==2 ? 0 : 2; break; case '\t': i = i==2 ? 3 : 0; break; case MVDOWN: if (i < 3) i++; } if (!i && pos==7) { pos = 6; while (pos && name[pos-1]==' ') pos--; } } } static int playagain_menu(const char **menu, int x, int y) { int ret = openmenu(menu, 2, 0, x, y, NULL); if (ret==2) exit(0); return ret; } static int hiscorebox(const char **menu, int x, int y) { int i = 0; while (i < 10 && hiscores[i].score >= player1.score) i++; if (i < 10) i++; while (is_outside_screen(x+24, 0)) x--; drawbox(x, y, 24, 11, "HIGHSCORES"); x += 2; show_hiscorelist5(x, y+2, i); if (playagain_menu(menu, x+2, y+8)) { clearbox(x+21, y, 0, 11); return 1; } return 0; } static int hiscore_congrats(const char **menu) { char name[8] = " "; int x = 9; int y = _HEIGHT_24L ? 7 : 3; setwcurs(0, 9, y); while (is_outside_screen(x+26, 0)) x--; drawbox(x, y, 26, 9, "CONGRATULATIONS!"); setcurs(x+2, y+2); printstr("You have a highscore!"); newln(x+2); printstr("Please enter your name"); entername: switch (hiscore_entername_menu(name, menu, x+4, y+4)) { case 0: return 0; case 1: if (savehiscore(name)) { if (x > 7) clearbox(33, y, 2, 9); return hiscorebox(menu, 9, y); } setcurs(x+2, y+2); printstr("ERROR! Could not save"); newln(x+2); printstr("score to file. "); goto entername; case 2: clearbox(32, y, 0, 9); return 1; } } int gameovermenu() { const char *menu[2] = {"Play again", "Exit"}; readhiscores(NULL); if (ishiscore()) return hiscore_congrats(menu); setwcurs(1, 2, 3); drawbox(2, 3, 17, 5, "GAME OVER"); return playagain_menu(menu, 4, 5); } vitetris-0.58.0/src/menu/gm_2p.c000066400000000000000000000023661344123051600163660ustar00rootroot00000000000000#undef TWOPLAYER #define TWOPLAYER 1 #include "menu.h" #include "internal.h" #include "../input/input.h" #include "../textgfx/textgfx.h" #include "../draw/draw.h" int gamemenu_2p(const char **menu, int x, int y, menuhandler *handlers) { int yy = y; int keypr; int i1 = 0; int i2 = 0; int *i = &i1; begin: draw_2p_menu_decor(1, x-1, y); draw_2p_menu_decor(2, x-1, y+GAMEMENU_LENGTH); x += 2; back: player_ = 1; drawmenu(menu, GAMEMENU_LENGTH-1, i1, x, y, handlers); player_ = 2; drawmenu(menu, GAMEMENU_LENGTH-1, i2, x, y+GAMEMENU_LENGTH, handlers); while (1) { setcurs(x, yy+*i); refreshwin(-1); keypr = getkeypress_block(0); if (keypr==STARTBTN && i1!=3 && i2==3) keypr |= PLAYER_2; else if (inputdevs_player[0]==2 && i1==3 && i2!=3 && keypr==(STARTBTN | PLAYER_2)) keypr = STARTBTN; if (!(keypr & PLAYER_2)) { player_ = 1; i = &i1; yy = y; } else { player_ = 2; i = &i2; yy = y+GAMEMENU_LENGTH; } setcurs(x, yy+*i); switch (handle_menuitem(menu, GAMEMENU_LENGTH-1, i, x, yy+*i, handlers, keypr)) { case 0: return 0; case 2: if (*i==3) { x -= 2; clearbox(0, y+9, 0, 4); inputsetup_box(player_, x, y); *i = 0; goto begin; } return 1; case 3: goto back; } } } vitetris-0.58.0/src/menu/gm_sock.c000066400000000000000000000117361344123051600170050ustar00rootroot00000000000000#include #include #include "menu.h" #include "../input/input.h" #include "../textgfx/textgfx.h" #include "../draw/draw.h" #include "../game/tetris.h" #include "../game/game.h" #include "../netw/sock.h" #undef SOCKET #define SOCKET 1 #include "internal.h" int yesno_menu(int x, int y) { const char *menu[2] = {"Yes", "No"}; int i = 0; int xx; while (1) { setcurs(x, y); printmenuitem("Yes", !i); printmenuitem("No", i); xx = i ? x+6 : x; setcurs(xx, y); refreshwin(-1); switch (handle_menuitem_2cols(menu, 2, &i, 1, xx, y, NULL, getkeypress_block(1 | SINGLE_PL))) { case 0: return 0; case 2: return !i; } } } static void printplayerlist(const char **menu, int n, int pos, int off, int x, int y) { const char *s; int i; setcurs(x, y); for (i=0; i 10) { setcurs(x+16, y+i); printstr(" (more) "); } newln(x); } } static int playerlist_menu(int n, int x, int y) { const char *menu[12]; int i, off; int keypr = 0; menu[n] = "-"; menu[n+1] = "Wait for other"; n += 2; i = off = 0; while (1) { if (i==0) { for (i=0; i2) i--; while (1) { if (!keypr) /* redraw once every second */ drawmenu(menu, 5, i, x, y, hs); setcurs(x, y+5); newln(x); if (!(sock_flags & CONNECTED)) { if (sock_flags & CONN_PROXY) { if (playerlist) { clearbox(x, y, 0, 12); show_playerlist(x, y); if (socket_fd > -1) { keypr = 0; continue; } } clearbox(x, y+6, 0, 6); if (socket_fd < 0) return 0; setcurs(x, y+6); } printstr("Waiting for opponent..."); } else { sock_sendplayer(); sock_sendbyte('h'); /* request height */ sock_sendbyte('-'); setattr_bold(); printstr("PLAYER 2"); cleartoeol(); setattr_normal(); newln(x+4); printstr("Level: "); putch(player2.startlevel+'0'); movefwd(4); printstr("Height: "); putch(player2.height+'0'); } newln(x); if (game->mode & MODE_BTYPE) { cleartoeol(); newln(x); setattr_bold(); printint("B-TYPE LINES %d", player1.lineslimit); setattr_normal(); newln(x); if (opponent_name[0]) newln(x); } else { newln(x); cleartoeol(); } if (opponent_name[0]) { if (my_name[0]) printstr(my_name); else printstr("You"); putch(' '); printstr(get_wonlost_stats(my_name, opponent_name)); putch(' '); printstr(opponent_name); cleartoeol(); newln(x); } setcurs(x, y+i); refreshwin(-1); keypr = getkeypress(1000, 0); if (!keypr) continue; switch (handle_menuitem(menu, 5, &i, x, y+i, hs, keypr)) { case 0: if (CONNECTED == (sock_flags & (CONNECTED | CONN_BROKEN))) { drawbox(x, y, 28, 6, NULL); setcurs(x+2, y+1); printstr("Are you sure you want to"); newln(x+2); printstr("close the connection?"); if (!yesno_menu(x+4, y+4) || playerlist_n > 0 && reconnect_server()) { clearbox(x, y, 28, 6); keypr = 0; continue; } } i = 1; if (game->mode & MODE_BTYPE) i += 2; if (opponent_name[0]) i += 2; clearbox(0, y+7, 0, i); return 0; case 2: player2.height = 0; if (i>1) i++; return i+1; } } } vitetris-0.58.0/src/menu/hslist.c000066400000000000000000000011761344123051600166660ustar00rootroot00000000000000#include #include "menu.h" #include "../input/input.h" #include "../textgfx/textgfx.h" #include "../hiscore.h" void show_hiscorelist(int x, int y) { char buf[320]; char *p; int n; setcurs(x, y); printmenuitem("Highscores", 1); newln(x); setcolorpair(MAGENTA_FG); printstr(" Name Score Lvl Lines"); newln(x); setattr_normal(); if (!readhiscores(NULL)) { printstr(" No saved scores"); newln(x); } else { n = gethiscorelist(buf); p = buf; while (n) { p[30] = '\0'; printstr(p); newln(x); p += 32; n--; } } refreshwin(-1); if (getkeypress_block(SINGLE_PL) == 'q') exit(0); } vitetris-0.58.0/src/menu/inputdev.c000066400000000000000000000055601344123051600172170ustar00rootroot00000000000000#include #include #include "menu.h" #include "../input/input.h" #include "../textgfx/textgfx.h" #include "../options.h" #undef JOYSTICK #define JOYSTICK 1 #include "internal.h" static char devices_str[14]; static void upd_devstr() { strcpy(devices_str, "keybd js0 js1"); if (num_joyst == 1) inputdevs_fd[2] = -1; if (num_joyst && (inputdevs_fd[1] > -1 || inputdevs_fd[2] > -1)) { if (inputdevs_fd[2] < 0) devices_str[9] = '\0'; if (inputdevs_fd[1] < 0) { devices_str[8] = '1'; devices_str[9] = '\0'; } } else devices_str[5] = '\0'; } static const char *getdevstr(int i) { char *p = devices_str; while (i) { p = strchr(p, ' '); if (!p) return NULL; p++; i--; } return p; } static int getdev(const char *key) { char *p; if (key && (p = strchr(devices_str, key[2])) && isdigit(*p)) return *p-'0'+1; return 0; } static const char *player_devstr(const char **sect_name) { const char *s = ""; const char *dev; if (player_) s = (player_==1) ? "player1" : "player2"; dev = getopt_str(s, "input"); if (sect_name) *sect_name = s; return dev; } static int inp_devhandler(int keypr, int *pos) { const char *sect_name; const char *dev = player_devstr(§_name); const char *dev2; int i = 0; union val v; upd_devstr(); if (dev) { do i++; while ((dev2 = getdevstr(i)) && strncmp(dev, dev2, 3)); if (!dev2) i = 0; else if (player_) { v.integ = inputdevs_player[getdev(dev)]; if (v.integ && v.integ != player_) i = 0; } } switch (keypr) { case 0: break; case MVLEFT: i--; break; case MVRIGHT: i++; break; case MVDOWN: case '\t': *pos = 2; return 2; default: return 0; } dev = getdevstr(i); if (!dev) return 1; printmenuitem_options(devices_str, i); if (!i) unsetoption(sect_name, "input"); else { strncpy(v.str, dev, 4); setoption(sect_name, "input", v, 1); } #if TWOPLAYER if (player_) { i = getdev(dev); inputdevs_player[i] = player_; if (!i) { sect_name = player_==1 ? "player2" : "player1"; if (!getdev(getopt_str(sect_name, "input"))) inputdevs_player[0] = 0; } } #endif if (keypr) { *pos = 1; return 2; } return 1; } int inp_devlist(int *dev, int x, int y) { const char *device = "Device"; menuhandler handler = inp_devhandler; int ret = 0; drawmenu(&device, 1, 0, x, y, &handler); while (1) { *dev = getdev(player_devstr(NULL)); if (ret == 3) break; inp_printkeys(*dev, x, y+1); ret = openmenu(&device, 1, 0, x, y, &handler); if (ret < 2) return 0; } setcurs(x, y); printmenuitem(device, 0); newln(x); return 1; } #ifndef NO_MENU int inputsetup_menuitem(int k, int *pos) { int i = 0; if (!num_joyst) { i = rarrow_menuitem(k, pos); cleartoeol(); return i; } if (inp_devhandler(k, &i)) { if (k && i!=1) movefwd(strlen(devices_str)); printstr(" ->"); if (i==1) return 3; return k <= MVRIGHT; } return 0; } #endif vitetris-0.58.0/src/menu/inputset.c000066400000000000000000000052241344123051600172310ustar00rootroot00000000000000#include #include "menu.h" #include "internal.h" #include "../input/input.h" #include "../textgfx/textgfx.h" #include "../draw/draw.h" #include "../lang.h" #if TWOPLAYER int player_ = 0; #endif static int inp_keypr(int i) { const char keypr[11] = {MVUP, MVDOWN, MVLEFT, MVRIGHT, A_BTN, B_BTN, MVUP, A_BTN, B_BTN, HARDDROP, MVDOWN}; int k = keypr[i]; if (player_) k |= player_==1 ? PLAYER_1 : PLAYER_2; if (i >= 6) k |= IN_GAME; return k; } void inp_printkeys(int dev, int x, int y) { const char *k; int i; x += 6; setcurs(x, y); for (i = 0; i < 11; i++) { k = getkeyfor_str(dev, inp_keypr(i)); printstr(k); putnchars(' ', 6-strlen(k)); if (i == 5) { x += 17; setcurs(x, y); } else newln(x); } } static int inp_setcurs(int x, int y, int i) { if (i >= 6) { x += 12; i -= 6; } setcurs(x, y+i); return x; } void inputsetup_menu(int pl, int x, int y) { const char *menu[11] = { " Up", "Dwn", "Lft", "Rgt", " A", " B", " Rotate ", " Rot cw ", NULL, "Harddrop", "Softdrop" }; char rot_acw[9] = " Rot acw"; int dev = 0; int i = 0; int xx, k; #ifdef JOYSTICK int devlist = num_joyst; if (devlist) { i = -1; setcurs(x, y); newln(x); y++; } #endif spellword(rot_acw+5); menu[8] = rot_acw; drawmenu(menu, 6, i, x, y, NULL); drawmenu(menu+6, 5, -1, x+12, y, NULL); #ifdef TWOPLAYER player_ = pl; #endif while (1) { #ifdef JOYSTICK if (devlist && i==-1) { if (!inp_devlist(&dev, x, y-1)) return; printmenuitem(menu[0], 1); i = 0; } #endif inp_printkeys(dev, x, y); xx = inp_setcurs(x, y, i); refreshwin(-1); k = setkeymapping(dev, inp_keypr(i)); #ifdef JOYSTICK if (devlist && (k==MVUP && !i || k=='\t' && i==10)) { printmenuitem(menu[i], 0); i = -1; continue; } #endif if (k==MVUP && !i) k = MVDOWN; else if (k==MVDOWN && i==10) { printmenuitem(menu[10], 0); inp_setcurs(x, y, i=0); printmenuitem(menu[0], 1); continue; } switch (handle_menuitem_2cols(menu, 11, &i, 6, xx, y+i%6, NULL, k)) { case 0: case 2: return; case 3: inp_setcurs(x, y, i); printmenuitem(menu[i], 1); } } } #ifndef NO_MENU static void printhelp(int x, int y) { setcurs(x, y); printstr("ESC to clear, TAB to skip,"); newln(x); printstr("ENTER to return"); } void inputsetup_box(int pl, int x, int y) { int h = 8; #ifdef JOYSTICK if (num_joyst) h++; #endif clearbox(x-1, y, 0, h+4); printhelp(x+2, y+h+2); setcurs(x, y); printmenuitem("Input Setup", 1); #ifdef TWOPLAYER if (!pl) printstr(" single"); printstr(" player"); if (pl) putch(pl+'0'); #endif drawbox(x, y+1, 31, h, NULL); inputsetup_menu(pl, x+1, y+2); clearbox(x, y, 0, h+4); } #endif vitetris-0.58.0/src/menu/internal.h000066400000000000000000000010731344123051600171750ustar00rootroot00000000000000#ifndef NULL #define NULL (void*)0 #endif void inp_printkeys(int dev, int x, int y); int inp_devlist(int *dev, int x, int y); #ifdef JOYSTICK int inputsetup_menuitem(int k, int *p); #else #define inputsetup_menuitem rarrow_menuitem #endif #ifdef TWOPLAYER #define GAMEMENU_LENGTH 7 int gamemenu_2p(const char **menu, int x, int y, menuhandler *handlers); #else #define gamemenu_2p(menu, x, y, handlers) 0 #endif #ifdef SOCKET int gamemenu_socket(const char **menu, int i, int x, int y, menuhandler *hs); #else #define gamemenu_socket(menu, i, x, y, handlers) 0 #endif vitetris-0.58.0/src/menu/invit.c000066400000000000000000000033151344123051600165060ustar00rootroot00000000000000#include #include #include "menu.h" #include "menuext.h" #include "../input/input.h" #include "../textgfx/textgfx.h" #include "../draw/draw.h" #undef TTY_SOCKET #define TTY_SOCKET 1 #include "../netw/sock.h" int yesno_menu(int x, int y); static int invit_dialog(const char *user, const char *tty, int x, int y) { char word[7]; const char *p = "wants to battle you. "; const char *q; int i, n; drawbox(x, y, 32, 7, "2P GAME INVITATION"); setcurs(x+2, y+2); printstr(user); printstr(" on "); printstr(tty); i = strlen(user) + strlen(tty) + 4; while (*p) { q = strchr(p, ' '); n = q-p; if (i+n > 27) { newln(x+2); i = 0; } else { putch(' '); i++; } strncpy(word, p, n); word[n] = '\0'; printstr(word); i += n; p = q+1; } setcurs(x+11, y+5); printstr("Accept? "); i = yesno_menu(x+20, y+5); clearbox(x, y, 32, 7); return i; } int select_2p_tty(int x, int y) { const char *items[4] = {"this terminal"}; char ttys[3][8]; char *msg; int i; if (!get_2p_ttys(ttys[0], 3)) return 1; for (i = 0; i < 3 && *ttys[i]; i++) items[i+1] = ttys[i]; i = dropdownlist(items, i+1, 0, x, y); if (!i) return 0; if (i > 1 && (msg = mksocket_local(ttys[i-2], 1))) { setcurs_end(); printstr(msg); free(msg); return 0; } return 1; } int menu_checkinvit(int x, int y) { const struct invit *inv; int accpt; char *msg; if (!invit) return 0; while (invit) { inv = invit; invit = NULL; accpt = invit_dialog(inv->user, inv->tty, x, y); msg = mksocket_local(inv->tty, 0); if (accpt) { if (!msg) { rminvitfile(); return 2; } setcurs_end(); printstr(msg); cleartoeol(); } else rmsocket(); if (msg) free(msg); } return -1; } vitetris-0.58.0/src/menu/men_allegro.c000066400000000000000000000061711344123051600176440ustar00rootroot00000000000000#include #include "../config.h" #include #include "menu.h" #include "menuext.h" #include "../textgfx/textgfx.h" #include "../draw/draw.h" #include "../game/tetris.h" #include "../input/input.h" #include "../options.h" #ifdef INET #define STARTUP_N 7 #else #define STARTUP_N 6 #endif #define STARTUP_Y (15-STARTUP_N) static void printmenuhelp(int y) { setcurs(0, y); printstr("Use the arrow keys or TAB to navigate,"); newln(0); printstr("ENTER to proceed, BACKSPACE or ESC to"); newln(0); printstr("go back. Exit at once with Q."); } #ifdef TWOPLAYER int startupmenu(int i) { while (1) { drawbox(5, STARTUP_Y-2, 22, STARTUP_N+4, NULL); printmenuhelp(19); i = startup_menu(i-1, 8, STARTUP_Y); # ifndef TTY_SOCKET if (!i) break; # else if (i==2 && !select_2p_tty(24, STARTUP_Y+1)) continue; if (!i) { clearbox(0, 6, 0, 16); if ((i = menu_checkinvit(1, 7)) == -1) { i = 1; continue; } if (!i) break; } setcurs_end(); cleartoeol(); textgfx_entermenu(); # endif clearbox(0, 6, 0, 16); break; } return i; } #endif /* TWOPLAYER */ int gamemenu() { int i = 0; #ifdef TWOPLAYER while (1) { if (!TWOPLAYER_MODE) show_hiscorelist5(5, GAMEMENU_LENGTH+9, 0); i = game_menu(0, 1, 7); if (i != 4) break; clearbox(5, GAMEMENU_LENGTH+9, 0, 5); inputsetup_box(0, 1, 7); } if (!i) clearbox(0, 7, 0, 14); #else while (1) { printmenuhelp(19); i = game_menu(i, 1, 7); if (!i) break; clearbox(0, 7, 0, GAMEMENU_LENGTH); if (i != 4 && i < GAMEMENU_LENGTH-1) break; clearbox(0, 19, 0, 3); switch (i) { case 4: inputsetup_box(0, 1, 7); i = 0; continue; case GAMEMENU_LENGTH-1: optionsmenu(); break; default: hiscorelist(); } i--; } #endif return i; } #ifdef INET int netplaymenu() { return netplay_menu(1, 7); } #endif void hiscorelist() { show_hiscorelist(1, 7); clearbox(0, 7, 0, 12); } static void help_alt_enter() { setcurs(2, 19); printstr("ALT-ENTER toggles fullscreen"); cleartoeol(); } static void draw_options_box() { drawbox(1, 7, 31, 11, "Options"); help_alt_enter(); } static int op_handler(int k, int *pos) { const struct termopt opt = {ASCII, "CP437 ASCII", "drawing"}; int i = *pos-2; if (i < 0) { if (k) { clearbox(0, 16, 0, 4); inputsetup_box(k-1, 1, 7); } draw_options_box(); return 1; } if (!i) { if (k == MVLEFT) i = 0; else if (k == MVRIGHT) i = 1; else { i = !getopt_int("", "fullscreen"); if (k == A_BTN) i = !i; else if (k) return 0; } printmenuitem_options("yes no", i); if (k) { union val v; v.integ = !i; setoption("", "fullscreen", v, 0); } i = 1; } else if (i == 1) { if (!k) { get_xy(&k, &i); setcurs(2, i+5); putnchars(HLINE, 28); help_alt_enter(); setcurs(k, i); k = 0; } i = term_optionhandler(k, &opt); } #ifndef NO_BLOCKSTYLES else i = select_blockstyle(k); #endif if (i == 3) { draw_tetris_logo(0, 0); draw_options_box(); } return i; } void optionsmenu() { const char *items[2] = {"Fullscreen", "Line Drawing"}; draw_options_box(); options_menu(items, 2, op_handler, 3, 9); clearbox(1, 7, 0, 11); } vitetris-0.58.0/src/menu/men_ansi.c000066400000000000000000000042601344123051600171460ustar00rootroot00000000000000#include #include "menu.h" #include "menuext.h" #include "../textgfx/textgfx.h" #include "../textgfx/ansivt.h" #include "../draw/draw.h" #include "../game/tetris.h" #include "../lang.h" #ifdef TWOPLAYER int startupmenu(int i) { while (1) { print_vitetris_ver(19, 4); i = startup_menu(i-1, 1, 4); # ifndef TTY_SOCKET if (!i) break; # else if (i==2 && !select_2p_tty(17, 5)) continue; if (!i && (i = menu_checkinvit(1, 4)) == -1) { i = 1; continue; } if (!i) break; setcurs_end(); printf("\033[K"); # endif clearbox(0, 4, 0, menuheight-4); break; } return i; } #endif /* TWOPLAYER */ int gamemenu() { int i = 1; #ifdef TWOPLAYER int h; if (!TWOPLAYER_MODE || game->mode & MODE_NETWORK) h = GAMEMENU_LENGTH+4; else { h = 17; while (menuheight < h) newln(2); } while (1) { i = game_menu(0, 1, 4); if (i==4) inputsetup_box(0, 1, 4); else break; } if (!i) clearbox(0, 4, 0, h-4); #else while (1) { i = game_menu(i-1, 1, 4); if (i==4) { setcurs(0, 13); printf("\033[K"); inputsetup_box(0, 1, 4); i = 1; } else if (i < GAMEMENU_LENGTH-1) break; else { clearbox(0, 4, 0, GAMEMENU_LENGTH); if (i == GAMEMENU_LENGTH-1) optionsmenu(); else hiscorelist(); } } #endif return i; } #ifdef INET int netplaymenu() { return netplay_menu(1, 4); } #endif void hiscorelist() { menuheight = 6; show_hiscorelist(1, 4); clearbox(0, 4, 0, menuheight-4); } static int op_handler(int k, int *pos) { const struct termopt opts[3] = { { WHITE_BG, "black white", "bg" }, { MONOCHROME, "16 mono", "color" }, #ifdef IBMGRAPHICS { ASCII, "CP437 ASCII", "drawing" } #else { ASCII, "VT100 ASCII", "drawing" } #endif }; int i = *pos-2; if (i < 0) { if (k) inputsetup_box(k-1, 1, 4); return 1; } if (!i && !k) menuheight = 11; if (i < 3) i = term_optionhandler(k, opts+i); #ifndef NO_BLOCKSTYLES else i = select_blockstyle(k); #endif if (i == 3) draw_tetris_logo(0, 0); return i; } void optionsmenu() { const char *items[3] = {"Term BG", NULL, "Line Drawing"}; char colors[8] = "Colours"; spellword(colors); items[1] = colors; options_menu(items, 3, op_handler, 1, 4); menuheight = 8; } vitetris-0.58.0/src/menu/men_curses.c000066400000000000000000000065621344123051600175270ustar00rootroot00000000000000#include #include #include "menu.h" #include "menuext.h" #include "../textgfx/textgfx.h" #include "../textgfx/curs.h" #include "../draw/draw.h" #include "../game/tetris.h" #ifdef INET #define STARTUP_N 7 #else #define STARTUP_N 6 #endif #define STARTUP_Y (15-STARTUP_N) static void printmenuhelp(int y) { if (term_height < y+5 || term_width < 48) return; setcurs(0, y); printstr("Use the arrow keys or TAB to navigate,"); newln(0); printstr("ENTER to proceed, BACKSPACE or ESC to"); newln(0); printstr("go back. Exit at once with Q."); } #ifdef TWOPLAYER int startupmenu(int i) { while (1) { drawbox(5, STARTUP_Y-2, 22, STARTUP_N+4, NULL); printmenuhelp(19); i = startup_menu(i-1, 8, STARTUP_Y); # ifndef TTY_SOCKET if (!i) break; # else if (i==2 && !select_2p_tty(24, STARTUP_Y+1)) continue; if (!i) { setcurs(5, STARTUP_Y-2); wclrtobot(window); if ((i = menu_checkinvit(1, 7)) == -1) { refresh(); setwcurs(0, 5, 7); i = 1; continue; } if (!i) break; } move(term_height-1, 0); clrtoeol(); refresh(); # endif setcurs(5, STARTUP_Y-2); wclrtobot(window); break; } return i; } #endif /* TWOPLAYER */ int gamemenu() { int i = 0; #ifdef TWOPLAYER int y = 7; while (1) { if (!TWOPLAYER_MODE) { if (term_height >= 23) show_hiscorelist5(5, GAMEMENU_LENGTH+9, 0); } else if (term_height < 23) { setcurs(1, 4); cleartoeol(); y = 5; } i = game_menu(0, 1, y); if (i != 4) break; wclrtobot(window); inputsetup_box(0, 1, 7); } if (!i) { setcurs(1, 4); wclrtobot(window); print_vitetris_ver(19, 4); } #else while (1) { printmenuhelp(19); i = game_menu(i, 1, 7); if (!i) break; clearbox(0, 7, 0, GAMEMENU_LENGTH); if (i != 4 && i < GAMEMENU_LENGTH-1) break; wclrtobot(window); switch (i) { case 4: inputsetup_box(0, 1, 7); i = 0; continue; case GAMEMENU_LENGTH-1: optionsmenu(); break; default: hiscorelist(); } i--; } #endif return i; } #ifdef INET int netplaymenu() { return netplay_menu(1, 7); } #endif void hiscorelist() { int y = 7; if (term_height < 22) y--; show_hiscorelist(1, y); clearbox(0, y, 0, 12); } static void help_cmdline() { if (term_height > 22) { setcurs(1, 20); printstr("-help for command-line options"); } } static void draw_options_box() { drawbox(1, 7, 31, 10+!(textgfx_flags & CYGWIN), "Options"); help_cmdline(); } static int op_handler(int k, int *pos) { const struct termopt opts[2] = { { WHITE_BG, "black white", "bg" }, { ASCII, "VT100 ASCII", "drawing" } }; int i = *pos-2; if (i < 0) { if (k) { setcurs(0, 16); wclrtobot(window); inputsetup_box(k-1, 1, 7); } draw_options_box(); return 1; } if (!i && !k) { getyx(window, i, k); setcurs(2, i+5+!(textgfx_flags & CYGWIN)); putnchars(HLINE, 28); help_cmdline(); setcurs(k, i); i = k = 0; } if (i < 1+!(textgfx_flags & CYGWIN)) i = term_optionhandler(k, opts+i); #ifndef NO_BLOCKSTYLES else i = select_blockstyle(k); #endif if (i == 3) { draw_tetris_logo(0, 0); if (!_MONOCHROME) { init_color_pairs(); if (*pos == 2) clearok(window, TRUE); } draw_options_box(); } return i; } void optionsmenu() { const char *items[2] = {"Term BG", "Line Drawing"}; int n = 1+!(textgfx_flags & CYGWIN); draw_options_box(); options_menu(items, n, op_handler, 3, 9); setcurs(0, 7); wclrtobot(window); } vitetris-0.58.0/src/menu/menu.h000066400000000000000000000054601344123051600163310ustar00rootroot00000000000000#ifndef menu_h #define menu_h /* menuhandler parameters: * keypress lower 8 bits of getkeypress return value * pos pointer to menu item index number >= 0 * * Return values: * 0 unhandled keypress (leave to default handler) * ESC go back * 1 stay in menu * 2 proceed * 3 redraw menu */ typedef int (*menuhandler)(int keypress, int *pos); /* Print a menu item, selected if sel. Leaves the cursor after name. */ void printmenuitem(const char *name, int sel); /* Print space-separated words. * sel_index is used to mark one word as selected (counting from zero). */ void printmenuitem_options(const char *str, int sel_index); /* Draw menu with n items and pos as selected index number. * handlers may be NULL or an array with some null pointers. */ void drawmenu(const char **menu, int n, int pos, int x, int y, menuhandler *handlers); /* Prints menu item(s) and calls menu handlers if given. * i is a pointer to update with new selected menu-item index. * x and y is the position of the current item and where the cursor is. * keypr is the return value of getkeypress. * This function calls exit for 'q'. * Default handler returns: * 0 go back (B button) * 1 no action * 2 proceed (A button) */ int handle_menuitem(const char **menu, int n, int *i, int x, int y, menuhandler *handlers, int keypr); /* Returns 0 if a handler returned 0. * Returns selected index + 1 if a handler returned 2. */ int openmenu(const char **menu, int n, int i, int x, int y, menuhandler *handlers); /* Handles a menu with two columns (extends handle_menuitem). * h is the number of items in the first column. * Returns 3 if column changed. */ int handle_menuitem_2cols(const char **menu, int n, int *i, int h, int x, int y, menuhandler *handlers, int keypr); /* Prints an editable text field with the cursor at pos. */ void printtextbox(const char *text, int pos); int rarrow_menuitem(int keypress, int *pos); /* Same as openmenu but different appearance. */ int dropdownlist(const char **items, int n, int i, int x, int y); /* The selected item is printed inside a box which may expand to a * dropdownlist. Returns * 0 if keypress != 0 and was unhandled -- nothing printed, * 3 if a dropdownlist was opened (redraw), * 1 otherwise -- the selected item was printed. */ int selectitem(const char **items, int n, int *i, int keypress); #ifndef TWOPLAYER # define GAMEMENU_LENGTH 10 # define player_ 0 #else # define GAMEMENU_LENGTH 7 extern int player_; /* 0 - single player 1 - player1 2 - player2 */ #endif void inputsetup_menu(int player, int x, int y); void inputsetup_box(int player, int x, int y); int game_menu(int i, int x, int y); void show_hiscorelist(int x, int y); void show_hiscorelist5(int x, int y, int i); int gameovermenu(); #endif /* !menu_h */ vitetris-0.58.0/src/menu/menucore.c000066400000000000000000000104741344123051600171760ustar00rootroot00000000000000#include /* exit */ #include #include #include "menu.h" #include "../input/input.h" #include "../textgfx/textgfx.h" void printmenuitem(const char *name, int sel) { #if !NO_MENU if (*name == '-') { putch(' '); if (!name[1]) putnchars('-', 16); else printstr(name); return; } #endif if (!sel) setcolorpair(MAGENTA_FG); else if (!_MONOCHROME) setcolorpair(WHITE_ON_BLUE); else setattr_standout(); if (sel && (textgfx_flags & TT_MONO)==TT_BLOCKS) { while (*name==' ') { putch(' '); name++; } putch('*'); } else putch(' '); printstr(name); putch(' '); setattr_normal(); movefwd(1); } void printmenuitem_options(const char *str, int sel) { char buf[16]; const char *p = str; int ret; while (1) { if (p = strchr(str, ' ')) { memcpy(buf, str, p-str); buf[p-str] = '\0'; } else strcpy(buf, str); if (!sel) { setattr_standout(); ret = printstr(buf); setattr_normal(); } else ret = printstr(buf); if (!ret || !p) break; putch(' '); str = p+1; sel--; } } void drawmenu(const char **menu, int n, int pos, int x, int y, menuhandler *handlers) { int i; setcurs(x, y); for (i = 0; i < n; i++) { printmenuitem(menu[i], (i==pos)); if (handlers && handlers[i]) handlers[i](0, &i); newln(x); } } #ifndef NO_MENU static int find_firstletter(const char **menu, int n, int i, int c) { int j = 1; c = toupper(c); while (i+j < n) { if (c == menu[i+j][0]) return j; j++; } for (j=0; j < i; j++) if (c == menu[j][0]) return j-i; return 0; } #endif int handle_menuitem(const char **menu, int n, int *i, int x, int y, menuhandler *handlers, int keypr) { int j = *i; int m; keypr &= 0xFF; if (keypr == ESC) return 0; printmenuitem(menu[j], 1); if (handlers && handlers[j]) switch (m = handlers[j](keypr, i)) { case 0: break; case ESC: return 0; default: return m; } switch (keypr) { case STARTBTN: case A_BTN: return 2; case B_BTN: case '\b': return 0; case 'q': exit(0); case MVUP: if (!j) return 1; #if NO_MENU m = -1; #else m = -1-(*menu[j-1]=='-'); #endif break; case '\t': if (j == n-1) { m = -j; break; } case MVDOWN: if (j < n-1) { #if NO_MENU m = 1; #else m = 1+(*menu[j+1]=='-'); #endif break; } default: #ifndef NO_MENU if (m = find_firstletter(menu, n, j, keypr)) break; #endif return 1; } setcurs(x, y); printmenuitem(menu[j], 0); setcurs(x, y+m); printmenuitem(menu[*i+=m], 1); return 1; } int openmenu(const char **menu, int n, int i, int x, int y, menuhandler *handlers) { drawmenu(menu, n, i, x, y, handlers); while (1) { setcurs(x, y+i); refreshwin(-1); /* refresh active window */ switch (handle_menuitem(menu, n, &i, x, y+i, handlers, getkeypress_block(SINGLE_PL))) { case 0: return 0; case 2: return i+1; #if !NO_MENU case 3: return openmenu(menu, n, i, x, y, handlers); #endif } } } int handle_menuitem_2cols(const char **menu, int n, int *i, int h, int x, int y, menuhandler *handlers, int keypr) { menuhandler *p; int j = *i; int m; keypr &= 0xFF; switch (keypr) { case MVUP: if (j == h) { m = -1; goto col; } break; case '\t': if (j == n-1) { m = -j; goto col; } case MVDOWN: if (j == h-1) { m = 1; goto col; } } if (j < h) { if (keypr == MVRIGHT && j+h < n) { m = h; goto col; } m = handle_menuitem(menu, h, i, x, y, handlers, keypr); } else { if (keypr == MVLEFT && j-h >= 0) { m = -h; goto col; } j = *i-h; p = NULL; if (handlers) p = handlers+h; m = handle_menuitem(menu+h, n-h, &j, x, y, p, keypr); *i = j+h; } return m; col: printmenuitem(menu[j], 0); *i += m; return 3; } void printtextbox(const char *text, int pos) { int underscore; if (_WHITE_BG) underscore = textgfx_flags & (ASCII | GNOME_TERM) || !_XTERM; else underscore = textgfx_flags & (MONOCHROME | TT_BLOCKS); while (*text) { setattr_normal(); if (!pos) setattr_standout(); else { if (_WHITE_BG) { if (!underscore || textgfx_flags & GNOME_TERM) setattr_underline(); } else setcolorpair(WHITE_ON_BLUE); } if (*text == ' ' && underscore) putch('_'); else putch(*text); text++; pos--; } setattr_normal(); } #if !NO_MENU int rarrow_menuitem(int k, int *p) { printstr("\b->"); return k==MVRIGHT ? 2 : 0; } #endif vitetris-0.58.0/src/menu/menuext.h000066400000000000000000000010401344123051600170400ustar00rootroot00000000000000int startup_menu(int i, int x, int y); int select_2p_tty(int x, int y); int menu_checkinvit(int x, int y); int netplay_menu(int x, int y); #ifdef menu_h void options_menu(const char **items, int n, menuhandler f, int x, int y); #endif struct termopt { unsigned char flag; const char *s; const char *key; }; int term_optionhandler(int k, const struct termopt *o); int getblockstyle(); int select_blockstyle(int k); /* Outer functions */ int startupmenu(int i); int gamemenu(); int netplaymenu(); void hiscorelist(); void optionsmenu(); vitetris-0.58.0/src/menu/netplay.c000066400000000000000000000077101344123051600170340ustar00rootroot00000000000000#include #include #include #include #include "menu.h" #include "menuext.h" #include "../input/input.h" #include "../textgfx/textgfx.h" #include "../netw/sock.h" #include "../options.h" #include "../draw/draw.h" extern FILE *inet_out; static char host_str[75]; static char name_str[18]; static int cursor = -1; static init_field(char *str, const char *val, int maxlen) { memset(str, ' ', maxlen+1); if (val) { strncpy(str, val, maxlen); while (!str[--maxlen]) str[maxlen] = ' '; } } static void printtextfield(char *s, int n) { int c = 0; int d = cursor - 31; if (d > 0) { s += d; n -= d; } else d = 0; if (n > 32) { c = s[32]; s[32] = '\0'; } if (cursor == -1) { s[n] = '\0'; printstr(s); s[n] = ' '; if (c) printstr("..."); } else printtextbox(s, cursor - d); if (c) s[32] = c; cleartoeol(); } static int get_field_len(const char *s, int n) { while (n > 0 && s[n-1] == ' ') n--; return n; } static int textfield(int k, int *pos) { char *s; int n, max; if (*pos == 0) { s = host_str; if (k == MVDOWN) cursor = -1; } else { s = name_str; if (k == MVUP) cursor = -1; } max = strlen(s); n = get_field_len(s, max); if (!k || k == '\t') cursor = -1; if (cursor == -1) { if (k == MVRIGHT) { if (!n) k = MVLEFT; else cursor = n-1; } if (k == MVLEFT || k == DEL) cursor = 0; if (isprintable(k)) { memset(s, ' ', max); cursor = 0; } } if (cursor == -1) { printtextfield(s, n); return 0; } if (!isprintable(k)) switch (k) { case MVLEFT: if (cursor > 0) cursor--; break; case MVRIGHT: if (cursor < max-1) cursor++; break; case BACKSPACE: if (!cursor) break; cursor--; case DEL: memmove(s+cursor, s+cursor+1, max-cursor-1); break; default: return 0; } else if (cursor < max-1 && s[max-2] == ' ') { memmove(s+cursor+1, s+cursor, max-cursor-2); s[cursor] = k; cursor++; } printtextfield(s, max); return 1; } static void printline(char *line) { int n = strlen(line); if (line[n-1] == '\n') line[n-1] = '\0'; printstr(line); } static void read_print_message(FILE *fp, int x, int y) { char line[80]; if (fp) { fseek(fp, 0, SEEK_SET); if (fgets(line, 80, fp)) { setcurs(x, y); printline(line); cleartoeol(); } if (fgets(line, 80, fp)) { newln(x); printline(line); } fclose(fp); } } static int try_connect(int x, int y) { char host[74]; char *s; int n; clearbox(x, y, 0, 2); setcurs(x, y); n = get_field_len(host_str, 73); if (!n) return 0; s = host_str; while (*s == ' ') { s++; n--; } memcpy(host, s, n); host[n] = '\0'; s = strrchr(host, ':'); if (s) { *s = '\0'; if (!s[1]) s = NULL; } if (!s) n = 34034; else { do s++; while (*s == ' '); n = -1; if (isdigit(*s)) n = atoi(s); if (n > 0xFFFF || n <= 0) { printstr("Invalid port number"); return 0; } } inet_out = tmpfile(); printstr("Connecting..."); newln(x); refreshwin(-1); n = mksocket_inet(host, n); read_print_message(inet_out, x, y); inet_out = NULL; return n; } static void save_connect_str(const char *key, char *str) { union val v; int n; v.p = str; n = get_field_len(str, strlen(str)); str[n] = '\0'; setoption("", key, v, 2); str[n] = ' '; } int netplay_menu(int x, int y) { const char *menu[2] = {"Host", "Your name"}; init_field(host_str, getopt_str("", "host"), 73); init_field(name_str, getopt_str("", "name"), 16); if (host_str[0] == ' ') memcpy(host_str, "localhost:34034", 15); setcurs(x, y); printstr("Connect:"); menuhandler handlers[2] = {textfield, textfield}; edit_mode = 1; while (openmenu(menu, 2, 0, x, y+2, handlers)) { drawmenu(menu, 2, -1, x, y+2, NULL); if (try_connect(x, y+5)) { save_connect_str("host", host_str); save_connect_str("name", name_str); edit_mode = 0; return 1; } newln(x); rmsocket(); if (host_str[0] == ' ') break; } edit_mode = 0; clearbox(x, y, 0, 7); return 0; } vitetris-0.58.0/src/menu/optsmenu.c000066400000000000000000000074421344123051600172340ustar00rootroot00000000000000#include #include "menu.h" #include "menuext.h" #include "../input/input.h" #include "../textgfx/textgfx.h" #include "../draw/draw.h" #include "../options.h" #include "../lang.h" #ifdef TWOPLAYER static int op_inputsetup_select(int x, int y) { const char *items[3] = { "single player", " player1", " player2" }; return dropdownlist(items, 3, 0, x+14, y); } #else #define op_inputsetup_select(x, y) 1 #endif static void save_bgdot() { union val v; v.str[0] = bgdot; v.str[1] = '\0'; setoption("term", "bgdot", v, 1); } static int op_bgdot(int k, int *pos) { const char *items[3] = {"dot", "bullet", "blank"}; int n = 3; int i = 0; int j; if (isprintable(k)) { if (k == '0') bgdot = ' '; else if (k == '~') bgdot = BULLET; else bgdot = k; save_bgdot(); k = 0; } if (_ASCII) { items[1] = items[2]; n--; } else if (bgdot == BULLET) i = 1; if (bgdot == ' ') i = n-1; j = i; k = selectitem(items, n, &i, k); if (i != j) { if (i == 0) bgdot = '.'; else if (i == n-1) bgdot = ' '; else bgdot = BULLET; save_bgdot(); } if (k != 1) return k; putch(bgdot); putch(' '); return 1; } static int op_tcolor(int k, int *pos) { char *c = tetrom_colors + *pos; if (k >= '1' && k <= '7') *c = k-'0'; else if (k == A_BTN) { *c += 1; if (*c == 8) *c = 1; } else if (k) return 0; setcolorpair(*c); putch(' '); putch(*c+'0'); putch(' '); setattr_normal(); return 1; } static int op_tcolor_gt4(int k, int *pos) { int i = *pos+4; return op_tcolor(k, &i); } static void tetrom_colors_menu(int x, int y) { const char *menu[7] = {"I", "J", "L", "O", "S", "T", "Z"}; menuhandler handlers[7] = { op_tcolor, op_tcolor, op_tcolor, op_tcolor, op_tcolor_gt4, op_tcolor_gt4, op_tcolor_gt4 }; int i = 0; if (y+6 >= term_height) y -= 7; drawbox(x, y, 19, 6, (char *) 0); x++; y++; drawmenu(menu, 4, 0, x, y, handlers); drawmenu(menu+4, 3, -1, x+9, y, handlers+4); autorep_a_b_btns = 1; while (1) { setcurs(x, y+i%4); refreshwin(-1); switch (handle_menuitem_2cols(menu, 7, &i, 4, x, y+i%4, handlers, getkeypress_block(SINGLE_PL))) { case 0: case 2: autorep_a_b_btns = 0; if (i >= 4) x -= 9; clearbox(x-1, y-1, 19, 6); return; case 3: x += i>=4 ? 9 : -9; setcurs(x, y+i%4); printmenuitem(menu[i], 1); } } } void options_menu(const char **items, int n, menuhandler f, int x, int y) { const char *menu[8] = {"Input Setup", "-"}; char tetr_colors[18] = "Tetromino Colours"; menuhandler handlers[8] = {rarrow_menuitem}; int i = 1; memcpy(&menu[2], items, n*sizeof(char *)); while (i <= n) handlers[++i] = f; #if !NO_BLOCKSTYLES menu[++i] = "Block Style"; handlers[i] = f; n++; #endif menu[++i] = "Board BG"; handlers[i] = op_bgdot; spellword(tetr_colors+10); menu[++i] = tetr_colors; handlers[i] = rarrow_menuitem; n += 4; i = 0; while (i = openmenu(menu, n, i, x, y, handlers)) { i--; if (!i) { f(op_inputsetup_select(x, y), &i); inputdevs_player[0] = 0; } else if (i == n-1) tetrom_colors_menu(x, y+i+1); else if (!handlers[i](STARTBTN, &i)) break; } clearbox(x, y, 0, n); } int term_optionhandler(int k, const struct termopt *o) { int flag = o->flag; union val v; switch (k) { case 0: break; case MVLEFT: textgfx_flags &= ~flag; break; case MVRIGHT: textgfx_flags |= flag; break; case A_BTN: textgfx_flags ^= flag; break; default: return 0; } printmenuitem_options(o->s, (textgfx_flags & flag)!=0); if (!k) return 1; v.integ = flag==MONOCHROME ? 2-k : k-1; setoption("term", o->key, v, 0); #if !NO_BLOCKSTYLES if ((textgfx_flags & (WHITE_BG | TT_MONO))==(WHITE_BG | TT_BLOCKS) || _TT_BLOCKS_BG && (!_WHITE_BG || _MONOCHROME) && getopt_int("term", "block") == -1) textgfx_flags ^= TT_BLOCKS | TT_BLOCKS_BG; #endif reset_block_chars(); return 3; } vitetris-0.58.0/src/menu/startup.c000066400000000000000000000020061344123051600170530ustar00rootroot00000000000000#include "menu.h" #include "menuext.h" #include "../options.h" #include "../game/tetris.h" /* MODE_BTYPE */ static int gm_mode(int k, int *pos) { const char *items[2] = {"A-type", "B-type"}; union val v; int i; int ret; v.integ = getopt_int("", "mode"); i = 1-!(v.integ & MODE_BTYPE); ret = selectitem(items, 2, &i, k); if (ret && k) { if (i) v.integ |= MODE_BTYPE; else v.integ &= ~MODE_BTYPE; setoption("", "mode", v, 0); } return ret; } int startup_menu(int i, int x, int y) { union val v; const char *menu[7] = { "1-Player Game", "2-Player Game", #ifdef INET "Netplay", #endif "Mode", "-------------", "Options", "Highscores" }; menuhandler handlers[7] = {0, 0, #ifdef INET 0, #endif gm_mode}; i = openmenu(menu, #ifdef INET 1 + #endif 6, i, x, y, handlers); if (i && i <= 3) { #ifdef INET if (i==3) v.integ = MODE_2PLAYER | MODE_NETWORK; else #endif v.integ = i; v.integ |= getopt_int("", "mode") & MODE_BTYPE; setoption("", "mode", v, 0); } return i; } vitetris-0.58.0/src/netw/000077500000000000000000000000001344123051600152205ustar00rootroot00000000000000vitetris-0.58.0/src/netw/Makefile000066400000000000000000000017431344123051600166650ustar00rootroot00000000000000include ../src-conf.mk OBJS = socket.o comm.o $(inet_obj) $(tty_socket_obj) config_h = ../config.h ../config2.h all: $(netw_lib)$(inet_obj) netw.ainet.o: $(OBJS) comm_inet.o -ar dc netw.a no_inet.o ar rs netw.a $(OBJS) comm_inet.o netw.a: $(OBJS) no_inet.o ../src-conf.mk -ar dc netw.a inet.o comm_inet.o ar rs netw.a $(OBJS) no_inet.o socket.o: socket.c sock.h internal.h ../input/input.h $(config_h) comm.o: comm.c sock.h ../game/tetris.h ../game/tetris2p.h \ ../input/input.h ../draw/draw.h comm_inet.o: comm_inet.c sock.h ../game/tetris.h inet.o: inet.c sock.h internal.h $(config_h) tty_socket.o: tty_socket.c sock.h internal.h $(CC) $(CCFLAGS) -c tty_socket.c no_inet.o: no_inet.c sock.h $(CC) $(CCFLAGS) -c no_inet.c .c.o: $(CC) $(CCFLAGS) -I.. -c $< gameserver: gameserver.c $(CC) $(CCFLAGS) -o gameserver gameserver.c clean: rm -f netw.a socket.o comm.o comm_inet.o inet.o tty_socket.o no_inet.o rm -f gameserver .PHONY: all netw.ainet.o clean vitetris-0.58.0/src/netw/comm.c000066400000000000000000000211761344123051600163260ustar00rootroot00000000000000#include #include #include #include "../game/tetris.h" #include "sock.h" #include "../game/tetris2p.h" #include "../input/input.h" #include "../draw/draw.h" int handle_server_message(); /* comm_inet.c */ char my_name[17] = ""; char opponent_name[17] = ""; static int pos_correct; void sock_sendbyte(char b) { writebytes(&b, 1); } void sock_initgame() { static char saved_mode; static char saved_lineslimit; opponent_name[0] = '\0'; if (sock_flags & CONN_PROXY) { game->mode = saved_mode; player1.lineslimit = saved_lineslimit; } else { saved_mode = game->mode; saved_lineslimit = player1.lineslimit; if (is_server) playerlist_n = 0; } if (is_server) player2.lineslimit = player1.lineslimit; else { sock_sendbyte('i'); sock_sendplayer(); if (waitinput_sock(500) || waitinput_sock(500)) sock_getkeypress(0); } } static void initgame_response() { char s[3] = "m"; sock_sendplayer(); s[1] = game->mode; s[2] = player1.lineslimit; writebytes(s, 3); } void sock_sendplayer() { char s[3] = "p"; s[1] = player1.startlevel; s[2] = player1.rotationsys; writebytes(s, 3); } static void recvplayer() { char s[2]; if (readbytes(s, 2)) { if (s[0] > 9 || s[0] < 0) { sock_flags |= CONN_BROKEN; return; } player2.startlevel = s[0]; player2.rotationsys = s[1]; writebytes("N_", 2); } } static void set_level_height(int flags) { char s[2]; int n; if (readbytes(s, 2) && !(flags & IN_GAME) && !game_over) { n = s[0]-'0'; if (n >= 0 && n <= 9) player1.startlevel = n; n = s[1]-'0'; if (n >= 0 && n <= 5) player1.height = n; } } static void sendname() { char s[17] = "N"; int i = 0; while (my_name[i] == '_') i++; if (my_name[i]) { strncpy(s+1, my_name+i, 16); writebytes(s, 17); } } static int getkey_cancel() { switch (getkeypress(500, SINGLE_PL)) { case ESC: case ESC | PLAYER_2: case '\b': return 1; case 'q': exit(0); } return sock_flags & CONN_BROKEN; } int sock_wait_pl2ingame() { print_game_message(1, "WAIT", 1); game->next = NULL; while (!(sock_flags & CONNECTED)) if (getkey_cancel()) return 0; writebytes("N_G", 3); sock_flags = WAIT_PL2INGAME | (sock_flags & ~SAME_HEIGHT); while (!(sock_flags & PL2_IN_GAME)) { if ((sock_flags & (CONN_PROXY | WAIT_PL2INGAME)) == CONN_PROXY) return sock_wait_pl2ingame(); if (getkey_cancel()) break; } sock_flags &= ~WAIT_PL2INGAME; return sock_flags & PL2_IN_GAME; } static void sendboard(int n) { char s[50] = "b"; unsigned char *b; uint_least32_t row; int i, j; if (!(sock_flags & PL2_IN_GAME)) return; s[1] = n; b = (unsigned char *) s + 2; i = 20; while (n) { row = player1.board[--i]; j = 0; do { b[j] = row & 0xFF; j++; } while (row >>= 8); b += 4; n--; } writebytes(s, (char *)b - s); } static int p1_height_lines() { int n = player1.height; switch (n) { case 0: break; case 1: case 2: n = 2*n+1; break; default: n = 2*(n+1); } return n; } static void p1_lines_height(int n) { n /= 2; if (n > 3) n--; player1.height = n; } static void copy_same_height(int n) { if (is_server) memcpy(player2.board, player1.board, 20*sizeof(uint_least32_t)); else { memcpy(player1.board, player2.board, 20*sizeof(uint_least32_t)); redrawboard(&player1, 19); sendboard(n); } sock_flags |= SAME_HEIGHT; } static int recvboard_read(char *s, int n) { while (n > 0) { if (!readbytes(s, 4)) return 0; s += 4; n--; } return 1; } static void recvboard() { char s[48]; unsigned char *b = (unsigned char *) s; uint_least32_t row; int n, m = 0; int i = 20; int j; if (!readbytes(s, 1)) return; n = *s; if (n < 1 || n > 12) { conn_broken(0); return; } if (!recvboard_read(s, n) || !tetrom_seq) return; if (!game->state) m = p1_height_lines(); if (!player1.height && sock_flags & SAME_HEIGHT) { m = n; p1_lines_height(n); } while (n) { row = b[3]; for (j = 2; j >= 0; j--) { row <<= 8; row |= b[j]; } player2.board[--i] = row; b += 4; n--; } n = 20-i; if (n == m) copy_same_height(n); redrawboard(&player2, 19); if (!game_running) print_press_key(); } void sock_initround() { char s[3] = "n1"; sock_flags &= ~PL2_GARBAGE; sock_sendbyte('G'); if (is_server) { s[2] = *tetrom_seq; writebytes(s, 3); s[1] = '2'; writebytes(s, 3); s[2] = tetrom_seq[1]; writebytes(s, 3); s[1] = '1'; writebytes(s, 3); } if (player1.height) sendboard(p1_height_lines()); } void sock_sendnext(const struct player *p, char n) { char s[3] = "n"; if (sock_flags & PL2_IN_GAME) { s[1] = '1'+(p == game->player); s[2] = n; writebytes(s, 3); } } static void recvnext() { struct tetr next; char s[2]; char *p = tetrom_seq; if (!p || !readbytes(s, 2) || s[1] > 6) return; switch (*s) { case '2': p += 2; case '1': break; default: return; } if (*p != 0x7F) p++; else { gettetrom(&next, s[1]); drawnext(game->player+(*s=='2'), &next); if (game->next) *game->next = next; } *p = s[1]; } void sock_sendpiece(const struct player *p) { char s[5] = "x"; if (sock_flags & PL2_IN_GAME) { int bl = player1.piece.blocks; s[1] = bl & 0xFF; s[2] = bl>>8; memcpy(s+3, &player1.piece.x, 2); writebytes(s, 5); } } static void recvpiece() { struct player *p = &player2; struct tetr t; char bl[2]; if (!readbytes(bl, 2) || !game_running) return; if (tetris2p[1].delay) { if (*tetris2p[1].clearedlines) { redrawboard(&player2, 19); *tetris2p[1].clearedlines = 0; } if (!p->piece.blocks) nextpiece_2p(p); } memcpy(&t, &p->piece, sizeof(struct tetr)); p->piece.blocks = bl[0] | bl[1]<<8; readbytes(&p->piece.x, 2); if (memcmp(&t, &p->piece, sizeof(struct tetr))) { clearblocks(p, t.blocks, t.x, t.y); drawpiece(p, p->piece.blocks, p->piece.x, p->piece.y); } pos_correct = 1; } void sock_sendgarbage_num(int n) { char s[2] = "g"; s[1] = n; writebytes(s, 2); } static int recvgarbage_num(int n) { if (n <= 12) sendboard(n); else { tetris2p[1].garbage[1] = n-12; sock_flags |= PL2_GARBAGE; if (!tetris2p[1].delay || tetris2p[1].falltm) { getgarbage_player2(); return 1; } } return 0; } void sock_sendwinner() { char s[2] = "w"; if (winner == &player1) s[1] = '2'; else if (winner == &player2) s[1] = '1'; else s[1] = '3'; writebytes(s, 2); } int sock_getkeypress(int flags) { signed char b; if (!waitinput_sock(0)) return 0; if (!(sock_flags & (CONNECTED | CONN_PROXY))) { accept_conn(); return 0; } if ((sock_flags & CONN_BROKEN) && !(flags & IN_GAME) && !game_over) { if (reconnect_server()) return '.'; return ESC; } if (playerlist && (sock_flags & PLIST_UNHANDLED)) { if (sock_flags & CONNECTED) conn_broken(0); else if (!game_over) return ESC; } if (!readbytes(&b, 1)) return 0; if (b=='G' && game_over) { sock_flags &= ~PL2_IN_GAME; sock_sendbyte(ESC); goto out; } if (pos_correct == 2) pos_correct = 0; if (pos_correct) pos_correct = 2; switch (b) { case ESC: sock_flags &= ~PL2_IN_GAME; break; case 'G': if (!(sock_flags & WAIT_PL2INGAME)) break; sock_flags |= PL2_IN_GAME; case '.': return '.'; case 'N': if (readbytes(&b, 1)) { if (b =='_') sendname(); else { opponent_name[0] = b; readbytes(opponent_name+1, 15); } } break; case 'P': if (handle_server_message()) return '.'; break; case 'b': recvboard(); break; case 'g': if (readbytes(&b, 1) && b > 0 && recvgarbage_num(b)) return '.'; break; case 'h': if (readbytes(&b, 1)) { if (isdigit(b)) player2.height = b-'0'; else { sock_sendbyte('h'); sock_sendbyte(player1.height+'0'); } } break; case 'i': if (sock_flags == (CONN_PROXY | IS_SERVER)) sock_flags = CONN_PROXY | IS_SERVER | CONNECTED; if (is_server) initgame_response(); break; case 'l': set_level_height(flags); break; case 'm': if (!(sock_flags & CONN_PROXY)) playerlist_n = 0; readbytes(&game->mode, 1); readbytes(&player1.lineslimit, 1); player2.lineslimit = player1.lineslimit; break; case 'n': recvnext(); break; case 'p': sock_flags &= ~PL2_IN_GAME; recvplayer(); break; case 's': if (game_over) return '\n'; break; case 'w': if (readbytes(&b, 1) && b >'0' && b <= '3') { winner = game->player + (b-'1'); return '.'; } break; case 'x': recvpiece(); break; default: if (b >= '\t' && b < ESC) conn_broken(0); if (!(flags & IN_GAME)) break; /* for backward compatibility */ if (b == HARDDROP || pos_correct && b == MVDOWN && hitbtm(&player2.piece, &player2)) return HARDDROP; if (b > 0 && b <= B_BTN) { if (tetris2p[1].delay && tetris2p[1].falltm) nextpiece_2p(&player2); return b; } } out: return sock_getkeypress(flags); } vitetris-0.58.0/src/netw/comm_inet.c000066400000000000000000000037361344123051600173470ustar00rootroot00000000000000#include #include #include "sock.h" #include "../game/tetris.h" struct player_id *playerlist = NULL; int playerlist_n = 0; void request_playerlist() { if ((sock_flags & (IS_SERVER | CONN_PROXY)) != IS_SERVER) { if (playerlist) { free(playerlist); playerlist = NULL; } playerlist_n = -1; sock_sendbyte('L'); } } void connect_to_player(struct player_id *p) { char s[19] = "C"; if (!p) { s[1] = '0'; writebytes(s, 2); } else { s[1] = '1'; s[2] = p->id; memcpy(s+3, p->name, 16); writebytes(s, 19); sock_sendbyte('i'); sock_sendplayer(); } } int reconnect_server() { char b; if (sock_flags & CONN_PROXY && reconnect_inet()) { sock_flags = CONN_PROXY; if (playerlist_n) request_playerlist(); sock_initgame(); return 1; } return 0; } static int recvplayerlist() { struct player_id *p; char s[20]; int n; if (readbytes(s, 1)) n = s[0]; if (n > 0) { playerlist_n = n; if (playerlist) free(playerlist); playerlist = malloc(n * sizeof(struct player_id)); p = playerlist; if (p) { while (readbytes(s, 20)) { p->id = (unsigned char) s[0]; memcpy(p->name, s+1, 16); p->name[16] = '\0'; memcpy(p->mode, s+17, 3); p->mode[3] = '\0'; p++; n--; if (!n) return 1; } request_playerlist(); } } return 0; } static void send_mode() { char s[3] = "m"; s[1] = game->mode; s[2] = player1.lineslimit; writebytes(s, 3); } int handle_server_message() { char b; if (readbytes(&b, 1)) { if (b =='L') { sock_flags = CONN_PROXY; if (!recvplayerlist()) return 0; sock_flags |= PLIST_UNHANDLED; } else if (b =='1') { sock_flags = CONN_PROXY | IS_SERVER; sock_initgame(); send_mode(); if (playerlist) { free(playerlist); playerlist = NULL; } } else if (b =='2') { sock_flags = CONN_PROXY | CONNECTED; if (waitinput_sock(500) || waitinput_sock(500)) { sock_getkeypress(0); sock_sendplayer(); } } return !game_over; } return 0; } vitetris-0.58.0/src/netw/gameserver.c000066400000000000000000000274371344123051600175410ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include /* Force same start level and height #define SAME_LEVEL_HEIGHT 1 */ #define MAX_CLIENTS 100 /* client flags */ #define FIRST_BYTE 1 #define AVAILABLE 2 #define MODE_BTYPE 4 #define IN_GAME 8 int listen_sock; int num_clients = 0; // largest used index + 1 int num_available = 0; struct client { int sock; char name[16]; // no null byte at end char flags; #ifdef SAME_LEVEL_HEIGHT char level; char height; #endif char lineslimit; short opponent; char wins; } clients[MAX_CLIENTS]; char fwd_buf[64]; int fwd_buf_n; int bind_listen(int sock, uint16_t port) { struct sockaddr_in addr; int len = sizeof(struct sockaddr_in); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sock, (struct sockaddr *) &addr, len) < 0) { perror("Could not bind socket"); return 0; } if (listen(sock, 10) < 0) { perror("listen"); return 0; } return 1; } void printerror(const char *s) { printf("ERROR %s: %s (errno=%d)\n", s, strerror(errno), errno); } void accept_conn(int sock) { struct sockaddr_in name; socklen_t len = sizeof(name); sock = accept(sock, (struct sockaddr *) &name, &len); if (sock < 0) { printerror("accept"); exit(1); } printf("player %d: ", num_clients+1); printf("connect from host %s\n", inet_ntoa(name.sin_addr)); struct client *c = clients + num_clients; c->sock = sock; strncpy(c->name, inet_ntoa(name.sin_addr), 16); c->flags = FIRST_BYTE; c->opponent = -1; } int fd_set_clients(fd_set *fdset, int nfds) { int i, fd; for (i=0; i < num_clients; i++) { fd = clients[i].sock; if (fd >= 0) { FD_SET(fd, fdset); if (fd >= nfds) nfds = fd+1; } } return nfds; } int waitinput_1sec(int sock) { fd_set set; struct timeval tmv; FD_ZERO(&set); while (1) { FD_SET(sock, &set); tmv.tv_sec = 1; tmv.tv_usec = 0; if (select(sock+1, &set, 0, 0, &tmv) < 0) { if (errno == EINTR) continue; printerror("select"); return 0; } return FD_ISSET(sock, &set); } } int readbytes(int sock, char *dest, int n) { int i; if (!waitinput_1sec(sock)) return 0; i = recv(sock, dest, n, 0); if (i == n) return 1; if (i < 0 && errno == EINTR) i = 0; else if (i <= 0) return 0; return readbytes(sock, dest+i, n-i); } /* read first byte of message */ int read_one_byte(int sock) { char b; if (readbytes(sock, &b, 1) && b > 0 && (b < '\t' || b >= '\033')) return b; return 0; } int writebytes(int sock, const char *buf, int n) { int i = send(sock, buf, n, 0); if (i == n) return 1; if (i < 0) { if (errno != EINTR) { printerror("send"); return 0; } i = 0; } return writebytes(sock, buf+i, n-i); } void set_mode_str(int i, char *s) { memset(s, 0, 3); if (clients[i].flags & MODE_BTYPE) { s[0] = 'B'; int lines = clients[i].lineslimit; if (lines < 10) s[1] = '0'+lines; else { s[1] = '0'+lines/10; s[2] = '0'+lines%10; } } } void send_playerlist(int sock) { char buf[20] = "PL"; buf[2] = num_available; writebytes(sock, buf, 3); int i; for (i=0; i < num_clients; i++) if (clients[i].flags & AVAILABLE) { buf[0] = i+1; memcpy(buf+1, clients[i].name, 16); set_mode_str(i, buf+17); writebytes(sock, buf, 20); } } void set_available(int i, int sock) { clients[i].flags |= AVAILABLE; num_available++; writebytes(sock, "\033P1", 3); #ifdef SAME_LEVEL_HEIGHT clients[i].height = -1; writebytes(sock, "h_", 2); #endif } void set_opponents(int i, int j) { printf("%s vs. %s\n", clients[j].name, clients[i].name); clients[i].opponent = j; clients[i].wins = clients[j].wins = 0; clients[j].opponent = i; clients[j].flags &= ~AVAILABLE; num_available--; writebytes(clients[i].sock, "P2", 2); #ifdef SAME_LEVEL_HEIGHT clients[i].level = -2; clients[j].level = -1; clients[i].height = clients[j].height; #endif } void first_available_opponent(int i) { int j; for (j=0; j < num_clients; j++) if (clients[j].flags & AVAILABLE) { set_opponents(i, j); break; } } int choose_opponent(int i, int j, const char *name) { if (j >= 0 && j < num_clients && (clients[j].flags & AVAILABLE) && !strncmp(clients[j].name, name, 16)) { set_opponents(i, j); return 1; } return 0; } void copy_name(char *dest, const char *name) { int i; for (i=0; i < 16; i++) { if (*name >= ' ' && *name <= '~') { *dest = *name; dest++; } name++; } } int send_opponent_name(int i) { char buf[17] = "N"; int sock = clients[i].sock; i = clients[i].opponent; if (i >= 0) { copy_name(buf+1, clients[i].name); return writebytes(sock, buf, 17); } return 1; } void get_client_name(int i, char *buf) { if (memcmp(clients[i].name, buf, 16)) { buf[16] = '\0'; printf("player %d: name %s\n", i+1, buf); } memcpy(clients[i].name, buf, 16); } void remove_client_elem(int i) { if (i+1 == num_clients) num_clients--; else { clients[i].sock = -1; clients[i].flags = 0; } } int remove_client(int i) { close(clients[i].sock); printf("player %d disconnected\n", i+1); if (clients[i].flags & AVAILABLE) num_available--; remove_client_elem(i); int j = clients[i].opponent; if (j >= 0) { if (fwd_buf_n) { writebytes(clients[j].sock, fwd_buf, fwd_buf_n); fwd_buf_n = 0; } clients[j].opponent = -1; if (num_available > 0) remove_client(j); else { set_available(j, clients[j].sock); if (i < j) { printf("player %d -> %d\n", j+1, i+1); clients[i] = clients[j]; remove_client_elem(j); i--; } } } while (num_clients > 0 && clients[num_clients-1].sock < 0) num_clients--; return i; } #ifdef SAME_LEVEL_HEIGHT void set_level_height(int i, int lev, int h) { char s[3] = "l"; s[1] = lev+'0'; s[2] = h+'0'; writebytes(clients[i].sock, s, 3); } int set_level(int i, int lev) { int j = clients[i].opponent; if (lev >= 0 && lev <= 9 && j >= 0) { if (clients[j].flags & IN_GAME) { if (clients[j].level >= 0) { lev = clients[j].level; set_level_height(i, lev, clients[j].height); } } else if (lev != clients[i].level && clients[i].level > -2) set_level_height(j, lev, clients[i].height); clients[i].level = lev; } return lev; } int set_height(int i, int h) { int j = clients[i].opponent; if (h >= 0 && h <= 5 && h != clients[i].height) { if (j >= 0) { if (clients[j].flags & IN_GAME) { h = clients[j].height; set_level_height(i, clients[j].level, h); } else set_level_height(j, clients[i].level, h); } clients[i].height = h; } return h; } #endif void set_wins(int i, int w) { int j = clients[i].opponent; if (j < 0) { clients[i].wins = 0; return; } if (w > 0) { if (w == 2) clients[i].wins++; if (w == 1) clients[j].wins++; if (clients[i].wins == 3 || clients[j].wins == 3) { printf("%s vs. %s %d-%d\n", clients[i].name, clients[j].name, clients[i].wins, clients[j].wins); w = 0; } } if (w == 0) clients[i].wins = clients[j].wins = 0; } int fwd_to_opponent(int i, char *buf, int n) { if (buf[0] == 'm') { if (buf[1] & MODE_BTYPE) { if (buf[2] > 25) buf[1] &= ~MODE_BTYPE; if (buf[2] < 5) buf[2] = 5; writebytes(clients[i].sock, buf, 3); } clients[i].flags &= ~MODE_BTYPE; clients[i].flags |= buf[1] & MODE_BTYPE; clients[i].lineslimit = buf[2]; } #ifdef SAME_LEVEL_HEIGHT else if (buf[0] == 'p') buf[1] = set_level(i, buf[1]); else if (buf[0] == 'h' && buf[1] != '-') buf[1] = set_height(i, buf[1]-'0') + '0'; #endif else if (buf[0] == 'w') set_wins(i, buf[1]-'0'); i = clients[i].opponent; if (i >= 0) { if (fwd_buf_n + n > 64) { if (!writebytes(clients[i].sock, fwd_buf, fwd_buf_n)) return 0; fwd_buf_n = 0; } memcpy(fwd_buf+fwd_buf_n, buf, n); fwd_buf_n += n; } return 1; } int has_more_input(int sock) { fd_set set; struct timeval tmv = {0}; FD_ZERO(&set); FD_SET(sock, &set); return select(sock+1, &set, 0, 0, &tmv) == 0 && FD_ISSET(sock, &set); } int handle_message(int i, int sock, int b) { char buf[48]; int n; if (!b) return remove_client(i); buf[0] = b; n = 0; switch (b) { case 'C': if (!readbytes(sock, buf, 1)) return remove_client(i); if (buf[0] == '1') { if (!readbytes(sock, buf, 17)) return remove_client(i); if (choose_opponent(i, buf[0]-1, buf+1)) return i; // else goto case 'L' } else { if (buf[0] == '0') set_available(i, sock); return i; } case 'L': if (clients[i].flags & AVAILABLE) return remove_client(i); if (num_available == 0) set_available(i, sock); else send_playerlist(sock); return i; case '\033': set_wins(i, 0); break; case 'G': clients[i].flags |= IN_GAME; break; case 'N': if (readbytes(sock, buf, 1)) { if (buf[0] == '_') { if (send_opponent_name(i)) return i; } else if (readbytes(sock, buf+1, 15)) { get_client_name(i, buf); return i; } } return remove_client(i); case 'b': case 'g': case 'h': case 'w': n = 1; break; case 'p': clients[i].flags &= ~IN_GAME; writebytes(sock, "N_", 2); case 'm': case 'n': n = 2; break; case 'x': n = 4; } if (n && !readbytes(sock, buf+1, n) || !fwd_to_opponent(i, buf, n+1)) return remove_client(i); if (b == 'b') { n = buf[1]; if (n > 0 && n <= 12) { n *= 4; if (!readbytes(sock, buf, n) || !fwd_to_opponent(i, buf, n)) i = remove_client(i); } } if (!has_more_input(sock)) return i; return handle_message(i, sock, read_one_byte(sock)); } void read_from_clients(fd_set *fdset) { int i; int sock; int b; for (i=0; i < num_clients; i++) { sock = clients[i].sock; if (sock < 0 || !FD_ISSET(sock, fdset)) continue; fwd_buf_n = 0; b = read_one_byte(sock); if (!b) { i = remove_client(i); continue; } if (clients[i].flags & FIRST_BYTE) { clients[i].flags = 0; if (b == 'i') { if (num_available == 0) set_available(i, sock); else first_available_opponent(i); } else if (b != 'L') { printf("player %d: invalid first byte x%X\n", i+1, b); i = remove_client(i); continue; } } i = handle_message(i, sock, b); if (fwd_buf_n) writebytes(clients[clients[i].opponent].sock, fwd_buf, fwd_buf_n); } } void sighandler(int sig) { int sock; if (sig != SIGPIPE) { close(listen_sock); while (num_clients > 0) { num_clients--; sock = clients[num_clients].sock; if (sock >= 0) close(sock); } exit(0); } } void write_logfile(const char *logfile) { fclose(stdout); stdout = fopen(logfile, "a"); if (!stdout) { perror("Could not open LOGFILE for writing"); exit(1); } } int main(int argc, char **argv) { int port = 34034; int sock; fd_set fdset; int nfds; printf("Usage: %s [PORT] [LOGFILE]\n", argv[0]); if (argc > 1) { port = atoi(argv[1]); if (port < 1) port = 1; if (port > 0xFFFF) port = 0xFFFF; } printf("PORT %d\n", port); sock = socket(PF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("Could not create socket"); return 1; } if (!bind_listen(sock, port)) { close(sock); return 1; } if (argc > 2) { fclose(stdout); stdout = fopen(argv[2], "w"); if (!stdout) { perror("Could not open LOGFILE for writing"); return 1; } } listen_sock = sock; signal(SIGINT, sighandler); signal(SIGTERM, sighandler); signal(SIGPIPE, sighandler); // ignore time_t t = 0; while (1) { FD_ZERO(&fdset); FD_SET(sock, &fdset); nfds = sock+1; if (!num_clients) puts("Listening for connections..."); else nfds = fd_set_clients(&fdset, nfds); if (select(nfds, &fdset, 0,0,0) < 0 && errno != EINTR) { printerror("select"); return 1; } read_from_clients(&fdset); if (FD_ISSET(sock, &fdset) && num_clients < MAX_CLIENTS) { accept_conn(sock); num_clients++; } if (argc > 2) write_logfile(argv[2]); if (time(NULL)-t > 12*60*60) { time(&t); printf(ctime(&t)); } } return 0; } vitetris-0.58.0/src/netw/inet.c000066400000000000000000000035651344123051600163340ustar00rootroot00000000000000#include #include #include "../config.h" #ifdef WIN32 #include #else # ifdef HAVE_SYS_TYPES_H # include # endif # include # include # include #endif #include "internal.h" #include "sock.h" FILE *inet_out = NULL; extern struct sockaddr *sock_addr; static struct in_addr *get_h_addr(const char *name) { struct hostent *h = gethostbyname(name); if (!h) { fprintf(inet_out, "Unknown host \"%s\"\n", name); return NULL; } return (struct in_addr *) h->h_addr; } static int getaddr(const char *name, unsigned short port) { struct sockaddr_in *addr; struct in_addr *h; if (sock_addr) free(sock_addr); addr = malloc(sizeof(struct sockaddr_in)); addr->sin_family = AF_INET; addr->sin_port = htons(port); if (name) { h = get_h_addr(name); if (!h) return 0; addr->sin_addr = *h; } else addr->sin_addr.s_addr = htonl(INADDR_ANY); sock_addr = (struct sockaddr *) addr; return 1; } int mksocket_inet(const char *name, unsigned port) { char *msg = mksocket(PF_INET); if (!inet_out) inet_out = stdout; if (msg) goto err; if (!getaddr(name, port)) return 0; if (!name) { msg = bind_listen(sizeof(struct sockaddr_in)); if (msg) goto err; fprintf(inet_out, "Listening for connections on " "port %d...\n", port); return 1; } fprintf(inet_out, "Connecting to %s on port %d...\n", name, port); if (connectsock(sizeof(struct sockaddr_in))) return 1; fprintf(inet_out, "FAILED! %s\n", sock_strerror()); return 0; err: fprintf(inet_out, "%s\n", msg); free(msg); return 0; } int reconnect_inet() { char *msg; if (is_inet()) { msg = mksocket(PF_INET); if (msg) free(msg); else if (connectsock(sizeof(struct sockaddr_in))) return 1; sock_flags = CONNECTED | CONN_BROKEN; } return 0; } int is_inet() { return sock_addr && sock_addr->sa_family == AF_INET; } vitetris-0.58.0/src/netw/internal.h000066400000000000000000000012201344123051600172000ustar00rootroot00000000000000extern struct sockaddr *sock_addr; const char *sock_strerror(); char *sock_errmsg(const char *descr); #define errmsg(descr) sock_errmsg(descr) char *mksocket(int domain); char *bind_listen(int size); int connectsock(int size); #ifndef INVALID_SOCKET #define INVALID_SOCKET -1 #endif #ifndef S_IREAD #define S_IREAD S_IRUSR #endif #ifndef S_IWRITE #define S_IWRITE S_IWUSR #endif #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif #ifndef EAGAIN #define EAGAIN EWOULDBLOCK #endif #ifndef offsetof #define offsetof(type, member) ((size_t) ((type *) 0)->member) #endif #undef SUN_PATH #define SUN_PATH(ptr) (((struct sockaddr_un *) (ptr))->sun_path) vitetris-0.58.0/src/netw/no_inet.c000066400000000000000000000004561344123051600170240ustar00rootroot00000000000000#include "sock.h" struct player_id *playerlist = (void*)0; int playerlist_n = 0; void request_playerlist() {} void connect_to_player(struct player_id *p) {} int reconnect_server() { return 0; } int handle_server_message() { return 0; } int reconnect_inet() { return 0; } int is_inet() { return 0; } vitetris-0.58.0/src/netw/sock.h000066400000000000000000000041631344123051600163340ustar00rootroot00000000000000/* socket flags */ #define IS_SERVER 1 #define CONNECTED 2 #define CONN_BROKEN 4 #define PL2_IN_GAME 8 #define WAIT_PL2INGAME 16 #define SAME_HEIGHT 32 #define PL2_GARBAGE 64 #define CONN_PROXY 128 #define PLIST_UNHANDLED 256 #ifndef SOCKET_EMPTY_DEFS extern int sock_flags; #else #define sock_flags 0 #endif #define is_server (sock_flags & IS_SERVER) extern char my_name[17]; extern char opponent_name[17]; extern struct player_id { unsigned char id; char name[17]; char mode[4]; } *playerlist; extern int playerlist_n; extern const struct invit { char user[16]; char tty[8]; } *invit; extern char this_tty[8]; void mkinvitfile(); int checkinvit(); void rminvitfile(); /* ttys should be of size 8*n - n strings of length 8 */ int get_2p_ttys(char *ttys, int n); /* tty is opponent's tty (may be NULL if server). * returns malloc'd error message on error, otherwise NULL */ char *mksocket_local(const char *tty, int server); /* makes server socket if name is NULL. * prints error message and returns 0 on failure */ int mksocket_inet(const char *name, unsigned port); int reconnect_inet(); int is_inet(); /* exits with error message on failure */ void connect_tty(const char *tty); /* returns the address of the listening socket or NULL */ char *get_socket_fname(); void rmsocket(); /* Game protocol functions */ void request_playerlist(); void connect_to_player(struct player_id *p); int reconnect_server(); #ifndef SOCKET_EMPTY_DEFS void sock_sendbyte(char byte); void sock_initgame(); void sock_sendplayer(); int sock_wait_pl2ingame(); void sock_initround(); #ifdef tetris_h void sock_sendnext(const struct player *p, char n); void sock_sendpiece(const struct player *p); #endif void sock_sendgarbage_num(int n); void sock_sendwinner(); #else /* if SOCKET_EMPTY_DEFS */ #define sock_sendbyte(b) #define sock_wait_pl2ingame() 0 #define sock_initround() #define sock_sendpiece(p) #define sock_sendgarbage_num(n) #define sock_sendwinner() #endif int sock_getkeypress(int flags); void conn_broken(int sig); void accept_conn(); void writebytes(const char *buf, int n); int readbytes(char *buf, int n); int waitinput_sock(unsigned msec); vitetris-0.58.0/src/netw/socket.c000066400000000000000000000076621344123051600166670ustar00rootroot00000000000000#include #include #include #include "../config.h" #ifdef WIN32 #include #else # ifdef HAVE_SYS_TYPES_H # include # endif # include # include # include #endif #ifdef UNIX #include /* sockaddr_un */ #include /* unlink */ #endif #include "sock.h" #include "internal.h" #include "../input/input.h" #ifdef WIN32 #define TEST_EINTR (WSAGetLastError() == WSAEINTR) #else #define TEST_EINTR (errno == EINTR) #endif int sock_flags = -1; struct sockaddr *sock_addr = NULL; #ifdef WIN32 static int winsock_started = 0; static SOCKET mysock = INVALID_SOCKET; #else typedef int SOCKET; #define mysock socket_fd #endif void conn_broken(int sig) { sock_flags = CONN_BROKEN | sock_flags & ~PL2_IN_GAME; } const char *sock_strerror() { #ifndef WIN32 return strerror(errno); #else if (winsock_started) switch (WSAGetLastError()) { case WSAENETDOWN: return "Network is down"; case WSAEADDRINUSE: return "Address already in use"; case WSAECONNREFUSED: return "Connection refused"; case WSAETIMEDOUT: return "Connection timed out"; } return ""; #endif } char *sock_errmsg(const char *descr) { int n = strlen(descr); const char *s = sock_strerror(); char *msg = malloc(n+strlen(s)+10); strcpy(msg, "ERROR! "); strcat(msg, descr); if (*s) { n += 7; msg[n] = ':'; msg[n+1] = ' '; strcpy(msg+n+2, s); } return msg; } static void closesock() { if (mysock != INVALID_SOCKET) { #ifdef WIN32 closesocket(mysock); #else close(socket_fd); #endif mysock = INVALID_SOCKET; } } char *mksocket(int domain) { SOCKET sock; #ifdef WIN32 WSADATA info; if (!winsock_started && WSAStartup(MAKEWORD(1,1), &info) != 0) return errmsg("Winsock startup failed"); winsock_started = 1; #endif closesock(); sock = socket(domain, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) return errmsg("Could not create socket"); mysock = sock; #ifdef WIN32 socket_fd = 1; #endif #ifdef SIGPIPE if (sock_flags == -1) signal(SIGPIPE, conn_broken); #endif sock_flags = 0; return NULL; } char *bind_listen(int size) { SOCKET sock = mysock; if (bind(sock, sock_addr, size) == -1) return errmsg("Could not bind socket"); if (listen(sock, 1) == -1) return errmsg("listen"); sock_flags |= IS_SERVER; return NULL; } int connectsock(int size) { if (connect(mysock, sock_addr, size) == -1) return 0; sock_flags = CONNECTED; return 1; } void accept_conn() { SOCKET sock = accept(mysock, NULL, NULL); closesock(); mysock = sock; sock_flags |= CONNECTED; } void writebytes(const char *buf, int n) { int i = send(mysock, buf, n, 0); if (i == n) return; if (i == -1) { if (!TEST_EINTR) return; i = 0; } writebytes(buf+i, n-i); } int waitinput_sock(unsigned msec) { #ifndef WIN32 return waitinput(socket_fd, msec); #else fd_set set; struct timeval tmv; int ret; if (mysock == INVALID_SOCKET) return 0; do { FD_ZERO(&set); FD_SET(mysock, &set); tmv.tv_sec = 0; tmv.tv_usec = 1000*msec; ret = select(0, &set, NULL, NULL, &tmv); } while (ret == -1 && TEST_EINTR); return ret > 0; #endif } static int waitinput_1sec() { int i; for (i=0; i<10; i++) if (waitinput_sock(100)) return 1; return 0; } int readbytes(char *buf, int n) { int i; if (sock_flags & CONN_BROKEN) return 0; if (!waitinput_1sec()) goto broken; i = recv(mysock, buf, n, 0); if (i == n) return 1; if (i == -1 && TEST_EINTR) i = 0; else if (i <= 0) { broken: conn_broken(0); return 0; } return readbytes(buf+i, n-i); } void rmsocket() { if (sock_addr) { #ifdef UNIX if (is_server && sock_addr->sa_family == AF_UNIX) unlink(SUN_PATH(sock_addr)); #endif if (sock_flags & (CONN_PROXY | CONNECTED) != (CONN_PROXY | CONNECTED)) { free(sock_addr); sock_addr = NULL; } } closesock(); socket_fd = -1; #ifdef WIN32 if (winsock_started) { WSACleanup(); winsock_started = 0; } #endif if (playerlist) { free(playerlist); playerlist = NULL; } } vitetris-0.58.0/src/netw/tty_socket.c000066400000000000000000000115231344123051600175560ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include "sock.h" #include "internal.h" const struct invit *invit = NULL; char this_tty[8] = ""; static int invit_fd = -1; static int get_this_tty() { char *s = ttyname(STDOUT_FILENO); int i; if (!s) return 0; if (!strncmp(s, "/dev/", 5)) i = 5; else if (strlen(s) < 8) i = 0; else { i = strlen(s)-7; if (s[i] == '/') i++; } strcpy(this_tty, s+i); return 1; } static void getfname(char *name, const char *tty) { int i; memcpy(name, "/tmp/vitetris-", 14); strncpy(name+14, tty, 7); name[21] = '\0'; for (i = 14; i < 20 && name[i]; i++) if (name[i] == '/') name[i] = '-'; } void mkinvitfile() { char name[22]; if (*this_tty || get_this_tty()) { getfname(name, this_tty); invit_fd = open(name, O_CREAT | O_RDONLY | O_NONBLOCK, S_IREAD | S_IWRITE | S_IWGRP | S_IWOTH); } } static int getowner(const char *tty, char *username) { char fname[22]; struct stat st; struct passwd *pw; getfname(fname, tty); if (stat(fname, &st) == -1) return 0; if (pw = getpwuid(st.st_uid)) { strncpy(username, pw->pw_name, 15); username[15] = '\0'; return 1; } return 0; } int checkinvit() { static struct invit inv; int i = 0; ssize_t n; if (invit || invit_fd == -1) return 0; memset(inv.tty, 0, 8); while (i < 8) { n = read(invit_fd, inv.tty+i, 1); if (n == -1 && (errno==EAGAIN || errno==EINTR)) continue; if (n < 1) break; if (inv.tty[i] == '\n') { inv.tty[i] = '\0'; break; } i++; } if (i==8 || !i && n<1 && lseek(invit_fd, 0, SEEK_CUR) > 0) { rminvitfile(); mkinvitfile(); i = 0; } if (i && getowner(inv.tty, inv.user)) { invit = &inv; return 1; } return 0; } void rminvitfile() { char name[22]; if (invit_fd > -1) { close(invit_fd); invit_fd = -1; getfname(name, this_tty); unlink(name); } } static int add_2p_tty(char *tty, const char *name) { struct stat st; char fname[22]; int i; getfname(fname, name); if (!islower(*name) || strchr(name, '.') || stat(fname, &st) < 0) return 0; if (time(NULL) - st.st_mtime > 3600) { unlink(fname); return 0; } strncpy(tty, name, 7); for (i = 1; i < 7 && tty[i]; i++) if (tty[i] == '-') tty[i] = '/'; if (!strcmp(tty, this_tty)) { memset(tty, 0, 7); return 0; } return 1; } int get_2p_ttys(char *ttys, int n) { DIR *d = opendir("/tmp"); struct dirent *e; int i; if (!d) return 0; memset(ttys, 0, 8*n); i = 0; while (i < n && (e = readdir(d))) { if (strncmp(e->d_name, "vitetris-", 9)) continue; if (add_2p_tty(ttys+8*i, e->d_name+9)) i++; } closedir(d); return i > 0; } static void getaddr(const char *tty, int server) { char fname[29]; struct sockaddr_un *addr; if (server) { tty = this_tty; if (!*tty) get_this_tty(); } getfname(fname, tty); strcat(fname+14, ".socket"); if (sock_addr) free(sock_addr); addr = malloc(offsetof(struct sockaddr_un, sun_path) + strlen(fname)+1); addr->sun_family = AF_UNIX; strcpy(addr->sun_path, fname); sock_addr = (struct sockaddr *) addr; } static char *inviteplayer(const char *tty) { char name[22]; int fd; int n = strlen(this_tty); getfname(name, tty); fd = open(name, O_WRONLY | O_APPEND); if (fd < 0) return errmsg(name); this_tty[n] = '\n'; while (write(fd, this_tty, n+1) == -1 && errno==EINTR) ; close(fd); this_tty[n] = '\0'; return NULL; } static char *errmsg_connect_local() { char *msg; char *s = malloc(strlen(SUN_PATH(sock_addr))+9); strcpy(s, "connect "); strcat(s, SUN_PATH(sock_addr)); msg = errmsg(s); free(s); return msg; } char *mksocket_local(const char *tty, int server) { char *msg = mksocket(PF_UNIX); int size; if (!msg) { getaddr(tty, server); size = offsetof(struct sockaddr_un, sun_path) + strlen(SUN_PATH(sock_addr)); if (server) { unlink(SUN_PATH(sock_addr)); msg = bind_listen(size); chmod(SUN_PATH(sock_addr), S_IREAD | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (!msg && tty) msg = inviteplayer(tty); } else if (!connectsock(size)) msg = errmsg_connect_local(); if (msg) rmsocket(); } return msg; } void connect_tty(const char *tty) { char *msg, *p; if (!strncmp(tty, "/dev/", 5)) tty += 5; printf("Connecting to %s...\n", tty); msg = mksocket_local(tty, 0); if (!msg) return; p = strchr(msg, '/'); puts(p); free(msg); if (!get_this_tty()) exit(1); if (!strncmp(tty, this_tty, 7)) { printf("%s is this terminal!\n", tty); exit(1); } puts("Failed."); printf("Sending invitation to %s...\n", tty); mkinvitfile(); if (msg = mksocket_local(tty, 1)) { puts(msg); free(msg); exit(1); } } char *get_socket_fname() { if (sock_addr) return SUN_PATH(sock_addr); return NULL; } vitetris-0.58.0/src/options.c000066400000000000000000000075211344123051600161070ustar00rootroot00000000000000#include #include #include #include "options.h" struct sect sect_hd = {""}; int strtoval(char *str, union val *val) { int n, i; while (isspace(*str)) str++; n = strlen(str); while (n && isspace(str[n-1])) n--; val->integ = 0; if (n==1 && *str=='0') return 0; if (n >= 4) { str[n] = '\0'; val->p = str; return 2; } i = *str=='-'; if (str[i]>'0' && str[i]<='9') { val->integ = atoi(str); i++; for (; istr, str, 4); if (n && n<4) val->str[n] = '\0'; return 1; } static struct sect *getsect(const char *name, struct sect **prev) { struct sect *s = §_hd; if (!name[0]) return s; while (s->next) { if (!strcmp(name, s->next->name)) { if (prev) *prev = s; return s->next; } s = s->next; } return NULL; } struct sect *addsect(const char *name) { struct sect *s = getsect(name, NULL); if (!s) { s = malloc(sizeof(struct sect)); strcpy(s->name, name); s->opts = NULL; s->next = sect_hd.next; sect_hd.next = s; } return s; } static struct option *newopt(const char *key, union val val, int tp) { struct option *o; int n = sizeof(struct option) + strlen(key) - 2; int m = 0; char *p; if (tp == 1 && val.str[3]) m = 5; if (tp == 2) m = strlen(val.p)+1; o = malloc(n+m); o->val = val; if (m) { p = (char *) o; p += n; if (tp == 2) { strncpy(o->val.str, val.p, 4); strcpy(p, val.p); } else { memcpy(p, val.str, 4); p[4] = '\0'; } tp = 1; } o->tp_key[0] = tp; strcpy(opt_key(o), key); return o; } void addopt(const char *key, union val val, int tp, struct sect *sect) { struct option *o = newopt(key, val, tp); if (!sect) sect = §_hd; o->next = sect->opts; sect->opts = o; } struct option *getoptions(const char *sect_name) { struct sect *s = getsect(sect_name, NULL); if (s) return s->opts; return NULL; } /* getopt might be declared in stdio.h */ static struct option *get_opt(const char *sect_name, const char *key) { struct option *o = getoptions(sect_name); while (o) { if (!strcmp(key, opt_key(o))) return o; o = o->next; } return NULL; } int getopt_int(const char *sect_name, const char *key) { struct option *o = get_opt(sect_name, key); if (o) return o->val.integ; return 0; } char *getopt_str(const char *sect_name, const char *key) { struct option *o = get_opt(sect_name, key); if (o) return opt_longstr(o); return NULL; } char *opt_longstr(struct option *o) { if (opt_isint(o)) return NULL; if (!o->val.str[3]) return o->val.str; return (char *) o + (sizeof(struct option) + strlen(opt_key(o)) - 2); } static void rmopt(const char *key, struct option *o) { struct option *p; while (o->next) { if (!strcmp(key, opt_key(o->next))) { p = o->next; o->next = p->next; free(p); } else o = o->next; } } void setoption(const char *sect_name, const char *key, union val val, int tp) { struct sect *s = addsect(sect_name); struct option *o; if (tp==0 || tp==1 && !val.str[3]) { o = s->opts; while (o) { if (!strcmp(key, opt_key(o))) { o->val = val; o->tp_key[0] = tp; rmopt(key, o); return; } o = o->next; } } addopt(key, val, tp, s); rmopt(key, s->opts); } void unsetoption(const char *sect_name, const char *key) { struct sect *s = getsect(sect_name, NULL); struct option *o; if (!s || !s->opts) return; o = s->opts; if (!strcmp(key, opt_key(o))) { s->opts = o->next; free(o); } else rmopt(key, o); } void freeoptions(const char *sect_name) { struct sect *s, *p; struct option *o; if (sect_name[0]) { s = getsect(sect_name, &p); if (!s) return; p->next = s->next; } else { while (sect_hd.next) freeoptions(sect_hd.next->name); s = §_hd; } while (o = s->opts) { s->opts = o->next; free(o); } if (sect_name[0]) free(s); else s->opts = NULL; } vitetris-0.58.0/src/options.h000066400000000000000000000021361344123051600161110ustar00rootroot00000000000000struct option { union val { int integ; char str[4]; const void *p; } val; struct option *next; char tp_key[4]; }; #define opt_key(o) ((o)->tp_key+1) #define opt_isint(o) ((o)->tp_key[0] == 0) #define opt_isstr(o) ((o)->tp_key[0] == 1) extern struct sect { char name[8]; struct option *opts; struct sect *next; } sect_hd; /* returns 0 if converted to int, 1 if copied as string. * If value is a string of length >= 4, remove trailing space from str, * set val->p to pos in str, return 2. */ int strtoval(char *str, union val *val); struct sect *addsect(const char *name); void addopt(const char *key, union val val, int tp, struct sect *sect); struct option *getoptions(const char *sect_name); int getopt_int(const char *sect_name, const char *key); char *getopt_str(const char *sect_name, const char *key); char *opt_longstr(struct option *o); /* type should be 0 if val is int, 1 if string, 2 if long string (val.p) */ void setoption(const char *sect_name, const char *key, union val, int type); void unsetoption(const char *sect_name, const char *key); void freeoptions(const char *sect_name); vitetris-0.58.0/src/pctimer.h000066400000000000000000000005161344123051600160610ustar00rootroot00000000000000#if __TURBOC__ #include "tcint8.h" #else #include "gccint8.h" #endif #if __TURBOC__ || __DJGPP__ < 2 #define pctimer_init(Hz) \ init8h(Hz); ticks_8h = 0 #define pctimer_exit() \ quit8h() #define pctimer_get_ticks() \ ticks_8h #define pctimer_time(start,stop) \ time8h(start, stop) #define pctimer_sleep(ms) \ delay8h(ms) #endif vitetris-0.58.0/src/src-conf.mk000066400000000000000000000011161344123051600163050ustar00rootroot00000000000000CCFLAGS = $(CFLAGS) $(CPPFLAGS) #CFLAGS = -O2 -Wall -pedantic -Wno-parentheses CFLAGS = -O2 DTWOPLAYER = -DTWOPLAYER=1 tetris2p_obj = tetris2p.o #DJOYSTICK = -DJOYSTICK=1 #joylinux_obj = joylinux.o select_obj = select.o #BACKEND = curses #DCURSES = -DCURSES=1 BACKEND = ansi #BACKEND = allegro #DALLEGRO = -DALLEGRO=1 #DXLIB = -DXLIB=1 DTERM_RESIZING = -DTERM_RESIZING=1 #DNO_MENU = -DNO_MENU=1 menuext_lib = menuext.a #DNO_BLOCKSTYLES = -DNO_BLOCKSTYLES=1 netw_lib = netw.a DSOCKET = -DSOCKET=1 DINET = -DINET=1 inet_obj = inet.o DTTY_SOCKET = -DTTY_SOCKET=1 tty_socket_obj = tty_socket.o vitetris-0.58.0/src/textgfx/000077500000000000000000000000001344123051600157345ustar00rootroot00000000000000vitetris-0.58.0/src/textgfx/Makefile000066400000000000000000000033661344123051600174040ustar00rootroot00000000000000include ../src-conf.mk OBJS = block.o win.o print.o ibmgfx.o \ $(BACKEND).o $(BACKEND)_win.o term.o resize.o textgfx.a: $(OBJS) rm -f textgfx.a ar rcs textgfx.a $(OBJS) term.o: term.c textgfx.h ../options.h ../config.h $(CC) $(CCFLAGS) -I.. -c term.c block.o: block.c textgfx.h ../options.h ../src-conf.mk $(CC) $(CCFLAGS) $(DNO_BLOCKSTYLES) -c block.c win.o: win.c textgfx.h ../draw/draw.h ../game/tetris.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(DTWOPLAYER) $(DNO_MENU) -c win.c print.o: print.c textgfx.h $(CC) $(CCFLAGS) -c print.c ibmgfx.o: ibmgfx.c $(CC) $(CCFLAGS) -c ibmgfx.c ansi.o: ansi.c ansivt.h textgfx.h ../input/termin.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(DNO_MENU) $(DNO_BLOCKSTYLES) -c ansi.c ansi_win.o: ansi_win.c ansivt.h textgfx.h \ ../game/tetris.h ../draw/draw.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(DTWOPLAYER) $(DNO_MENU) -c ansi_win.c curses.o: curses.c curs.h textgfx.h ../input/termin.h $(CC) $(CCFLAGS) $(CURSES_INC) -c curses.c curses_win.o: curses_win.c curs.h textgfx.h \ ../game/tetris.h ../draw/draw.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(CURSES_INC) $(DTWOPLAYER) $(DNO_MENU) -c curses_win.c allegro.o: allegro.c textgfx.h alleg.h ../options.h ../lang.h ../config.h $(CC) $(CCFLAGS) -I.. -c allegro.c allegro_win.o: allegro_win.c textgfx.h alleg.h allegro_icon.h \ ../game/tetris.h ../draw/draw.h ../config.h $(CC) $(CCFLAGS) -I.. -c allegro_win.c resize.o: resize.c textgfx.h curs.h \ ../game/tetris.h ../draw/draw.h ../src-conf.mk $(CC) $(CCFLAGS) -I.. $(CURSES_INC) $(DTWOPLAYER) $(DNO_MENU) $(DCURSES) $(DTERM_RESIZING) $(DSOCKET) -c resize.c clean: rm -f textgfx.a $(OBJS) rm -f ansi.o ansi_win.o curses.o curses_win.o allegro.o allegro_win.o rm -f curse~60.o alleg~jn.o .PHONY: clean vitetris-0.58.0/src/textgfx/alleg.h000066400000000000000000000002471344123051600171740ustar00rootroot00000000000000extern char margin_x; extern int win_x; extern int win_y; extern BITMAP *virt_screen; extern int refresh_needed; extern char blit_rect[4]; void toggle_fullscreen(); vitetris-0.58.0/src/textgfx/allegro.c000066400000000000000000000247751344123051600175440ustar00rootroot00000000000000#include #include #include #include #include /* for reading stdout.tmp etc. */ #include "../config.h" #include #ifdef UNIX #include /* _xwin.application_name, _xwin.application_class */ #endif #include "textgfx.h" #include "alleg.h" #include "../options.h" #include "../lang.h" #include "../version.h" #include "../input/keyboard.h" #if defined ALLEGRO_WITH_XWINDOWS && defined ALLEGRO_USE_CONSTRUCTOR #include "allegro_icon.h" extern void *allegro_icon; CONSTRUCTOR_FUNCTION(static void _set_allegro_icon()); static void _set_allegro_icon() { allegro_icon = icon_xpm; } #endif void blockstyle_from_option(const struct option *o); int ibmgfx(int ch); unsigned textgfx_flags = HEIGHT_24L; char term_width = 80; char term_height = 25; static char curs_x = 0; static char curs_y = 0; char margin_x = 0; int win_x = 0; int win_y = 0; BITMAP *virt_screen = NULL; int refresh_needed = 0; char blit_rect[4] = {0}; int close_button_pressed = 0; static FONT *font8x16; static int vgacolors[16]; static unsigned char bg_color; static unsigned char fg_color; #ifdef UNIX static struct sigaction allegro_sigint_handler; #endif void gettermsize() {} void settermwidth(int w) {} void settermheight(int h) {} void gettermoptions() { struct option *o = getoptions("term"); for (; o; o = o->next) { if (!strcmp(opt_key(o), "drawing")) { if (o->val.integ) textgfx_flags |= ASCII; } else if (!strcmp(opt_key(o), "color")) { if (!o->val.integ) textgfx_flags |= MONOCHROME; } else blockstyle_from_option(o); } reset_block_chars(); } #ifdef UNIX static void sigint_handler(int sig) { textgfx_end(); allegro_sigint_handler.sa_handler(sig); } #endif static void load_pc8x16_font() { char fname[256]; int n; char *p; get_executable_name(fname, sizeof(fname)); n = strlen(fname); do n--; while (fname[n] !='\\' && fname[n] !='/'); fname[n] = '\0'; append_filename(fname, fname, "pc8x16.fnt", sizeof(fname)); font8x16 = load_font(fname, NULL, NULL); if (font8x16) return; p = getenv("ALLEGRO"); if (p) { strncpy(fname, p, sizeof(fname)); append_filename(fname, fname, "vitetris", sizeof(fname)); set_allegro_resource_path(5, fname); } #ifdef UNIX set_allegro_resource_path(4, "/usr/share/allegro/vitetris"); set_allegro_resource_path(3, "/usr/share/allegro"); set_allegro_resource_path(2, "/usr/local/share/allegro/vitetris"); set_allegro_resource_path(1, "/usr/local/share/allegro"); #endif if (find_allegro_resource(fname, "pc8x16.fnt", 0,0,0,0,0, sizeof(fname)) == 0) font8x16 = load_font(fname, NULL, NULL); } static void close_btn() { close_button_pressed = 1; } static void lost_focus() { textgfx_flags |= LOST_FOCUS; clear_keybuf(); } static void got_focus_back() { textgfx_flags &= ~LOST_FOCUS; kb_flushinp(); refresh_needed = 1; refreshscreen(); } static int setgfxmode(int fullscreen) { if (!fullscreen && set_gfx_mode(GFX_AUTODETECT_WINDOWED, 512, 400, 0, 0) == 0) { term_width = 64; set_display_switch_mode(SWITCH_BACKGROUND); set_display_switch_callback(SWITCH_OUT, lost_focus); return 1; } if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) == 0) { term_width = 80; set_display_switch_mode(SWITCH_PAUSE); return 1; } if (get_color_depth() != 8) { set_color_depth(8); return setgfxmode(fullscreen); } set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to set any graphics mode:\n" "%s\n", allegro_error); return 0; } BITMAP *set_screen(int fullscreen) { const unsigned char vgargb[16][3] = { 0, 0, 0, /* 0 black */ 170, 0, 0, /* 1 red */ 0,170, 0, /* 2 green */ 170, 85, 0, /* 3 yellow */ 0, 0,170, /* 4 blue */ 170, 0,170, /* 5 magenta */ 0,170,170, /* 6 cyan */ 170,170,170, /* 7 white */ 85, 85, 85, 255, 85, 85, 85,255, 85, 255,255, 85, 85, 85,255, 255, 85,255, 85,255,255, 255,255,255 }; const unsigned char *rgb; if (!setgfxmode(fullscreen)) exit(1); clear_bitmap(screen); if (set_display_switch_callback(SWITCH_IN, got_focus_back) == -1) set_display_switch_mode(SWITCH_PAUSE); BITMAP *bmp = create_bitmap(8 * term_width, 400); clear_bitmap(bmp); set_clip_state(bmp, 0); set_clip_state(screen, 0); int i; for (i=0; i<16; i++) { rgb = &vgargb[i][0]; vgacolors[i] = makecol(rgb[0], rgb[1], rgb[2]); } return bmp; } #if WIN32 && !ALLEGRO_USE_CONSOLE static int printline(char *line) { int n = strlen(line); int c = 0; if (line[n-1] == '\n') line[--n] = '\0'; if (n > 64 && is_windowed_mode()) { c = line[64]; line[64] = '\0'; } printstr(line); if (!c || curs_y == 24) return 0; line[64] = c; curs_y++; printstr(line + 64); return 1; } #endif void textgfx_init() { #ifdef UNIX strcpy(_xwin.application_name, "vitetris"); strcpy(_xwin.application_class, "Vitetris"); #endif if (install_allegro(SYSTEM_AUTODETECT, &errno, NULL) != 0) exit(1); #ifdef UNIX sigaction(SIGINT, NULL, &allegro_sigint_handler); signal(SIGINT, sigint_handler); #endif load_pc8x16_font(); set_window_title(VITETRIS_VER); set_close_button_callback(close_btn); #ifndef UNIX /* Seems to cause seg fault later quite randomly on Linux */ int depth = desktop_color_depth(); if (depth != 0) set_color_depth(depth); #endif virt_screen = set_screen(getopt_int("", "fullscreen")); lang |= LATIN1; if (!font8x16) { font8x16 = font; textgfx_flags |= ASCII; } setattr_normal(); #if WIN32 && !ALLEGRO_USE_CONSOLE if (exists("stdout.tmp")) { FILE *fp; freopen("stdout2.tmp", "w", stdout); fp = fopen("stdout.tmp", "r"); if (fp) { char line[80]; int i; for (i=0; i < 25 && fgets(line, 80, fp); i++) { setcurs(0, i); i += printline(line); } fclose(fp); if (i) { refreshscreen(); if (!strncmp(line, "Press ", 6)) { install_keyboard(); clear_keybuf(); readkey(); remove_keyboard(); } } } freopen("stdout.tmp", "w", stdout); delete_file("stdout2.tmp"); } #endif } void textgfx_end() { if (!virt_screen) return; destroy_bitmap(virt_screen); virt_screen = NULL; if (font8x16 != font) destroy_font(font8x16); allegro_exit(); } void toggle_fullscreen() { BITMAP *bmp = set_screen(is_windowed_mode()); if (bmp->w == virt_screen->w) destroy_bitmap(bmp); else { if (bmp->w > virt_screen->w) { int h = 400; if (in_menu) { blit(virt_screen, screen, 0, 384, 0, 464, 512, 16); h = 384; } blit(virt_screen, bmp, 0, 0, 64, 0, 512, h); curs_x += 8; } else { blit(virt_screen, bmp, 64, 0, 0, 0, 512, 400); curs_x -= 8; } margin_x = getmargin_x(); destroy_bitmap(virt_screen); virt_screen = bmp; } refresh_needed = 1; refreshscreen(); } void setcurs(int x, int y) { x += win_x + margin_x; y += win_y; curs_x = x; curs_y = y; } void movefwd(int n) { curs_x += n; } void newln(int x) { x += win_x + margin_x; curs_x = x; curs_y++; } void setcurs_end() { curs_x = 0; curs_y = 24; } int is_outside_screen(int x, int y) { return x + win_x + margin_x >= term_width || y + win_y >= 25; } void get_xy(int *x, int *y) { *x = curs_x - win_x - margin_x; *y = curs_y - win_y; } void refreshscreen() { int y = 0; if (!refresh_needed) return; if (!is_windowed_mode()) y = 40; acquire_screen(); blit(virt_screen, screen, 0, 0, 0, y, 8*term_width, 400); release_screen(); refresh_needed = 0; memset(blit_rect, 0, 4); } static void update_blit_rect(char x, char y, char x2) { if (x < blit_rect[0] || !blit_rect[0]) blit_rect[0] = x; if (y < blit_rect[1] || !blit_rect[1]) blit_rect[1] = y; if (x2 > blit_rect[2]) blit_rect[2] = x2; if (y > blit_rect[3]) blit_rect[3] = y; } void cleartoeol() { int y = 16*curs_y; int maxx = term_width-1; rectfill(virt_screen, 8*curs_x, y, 8*maxx, y+15, 0); refresh_needed = 1; update_blit_rect(curs_x, curs_y, maxx); } void set_color_pair(int clr) { int bg = 0; int bold = 1; if (_MONOCHROME) { if (clr == MAGENTA_FG) setattr_bold(); return; } if (clr & 64) { bg = clr & 7; clr = clr>>3 & 7; } else switch (clr) { case MAGENTA_FG: clr = 5; break; case WHITE_ON_BLUE: clr = 7; bg = 4; break; case BOARD_BG_COLOR: clr = 4; bold = 0; break; case BOARD_FRAME_COLOR: clr = 4; bold = 0; break; case RED_FG: clr = 1; break; case YELLOW_ON_BLUE: clr = 3; bg = 4; break; case YELLOW_ON_GREEN: clr = 3; bg = 2; break; default: if (clr & 16) clr &= 7; else bg = clr; } if (textgfx_flags & BLACK_BRACKETS && bg == clr) { clr = 0; bold = 0; } if (!_TT_BLOCKS) bg_color = bg; if (bold) clr |= 8; fg_color = clr; } void setattr_normal() { bg_color = 0; fg_color = 7; } void setattr_standout() { bg_color = fg_color; fg_color = 0; } void setattr_bold() { if ((textgfx_flags & TT_MONO) != TT_MONO && fg_color < 8) fg_color |= 8; } void setattr_underline() {} static int to_cp437(int ch) { const char *latin1 = "ÅÄÖÜåäöü"; const char *cp437 = "\x8F\x8E\x99\x9A\x86\x84\x94\x82"; const char *p; p = strchr(latin1, ch); if (p) return (unsigned char) cp437[p-latin1]; return '?'; } static void text_out(const char *s, int n) { int x = 8 *curs_x; int y = 16*curs_y; int bg = vgacolors[bg_color]; int fg = vgacolors[fg_color]; if (*s == '|' && n == 1) { rectfill(virt_screen, x, y, x+7, y+15, bg); rectfill(virt_screen, x+3, y, x+4, y+12, fg); } else { if (font == font8x16) { rectfill(virt_screen, x, y, x+(8*n)-1, y+15, bg); y += 4; } textout_ex(virt_screen, font8x16, s, x, y, fg, bg); } refresh_needed = 1; update_blit_rect(curs_x, curs_y, curs_x+n-1); curs_x += n; } void put_ch(int ch) { char s[2] = ""; int trans = 0; if (ch == '\b') { curs_x--; return; } if (ch < 0) ch = (unsigned char) ch; if (ch & 0x80) ch = to_cp437(ch); if (ch == TEXTURE2 && textgfx_flags & (TT_BLOCKS | BLACK_BRACKETS)) ch = ' '; if (ch & 0x100) { if (_ASCII) { putch_ascii(ch); return; } ch = (unsigned char) ibmgfx(ch); if (ch < 32) trans = 32; } if (ch == 0xFA) trans = -0x80; else if (ch >= 0x80) trans = -0x60; if (trans) { transpose_font(font8x16, trans); s[0] = ch + trans; text_out(s, 1); transpose_font(font8x16, -trans); } else { s[0] = ch; text_out(s, 1); } } int printstr(const char *str) { if (!str[0]) return 0; while (str[0] && curs_x < term_width) { putch(str[0]); str++; } return 1; } void printint(const char *fmt, int d) { char buf[80]; int n = usprintf(buf, fmt, d); text_out(buf, n); } void printlong(const char *fmt, long d) { char buf[80]; int n = usprintf(buf, fmt, d); text_out(buf, n); } int default_bgdot() { return BULLET; } vitetris-0.58.0/src/textgfx/allegro_icon.h000066400000000000000000000050371344123051600205470ustar00rootroot00000000000000/* XPM */ static char * icon_xpm[] = { "48 48 3 1", " c None", ". c #AA0000", "+ c #FF5555", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. "}; vitetris-0.58.0/src/textgfx/allegro_win.c000066400000000000000000000032501344123051600204020ustar00rootroot00000000000000#include "../config.h" #include #include "textgfx.h" #include "alleg.h" #include "../game/tetris.h" #include "../draw/draw.h" static int window; void setwcurs(int win, int x, int y) { if (win != window) { getwin_xy(win, &win_x, &win_y); window = win; } setcurs(x, y); } void refreshwin(int win) { static int redraw; struct player *p; int x, y, y2, w, h; if (redraw) return; if (!game || !game_running) { if (win == 1 || win == 2) { p = &game->player[win-1]; redraw = 1; if (game_paused) redrawboard(p, 19); else redrawboard(p, 3); redraw = 0; } refreshscreen(); return; } if (!refresh_needed) return; x = 8 *blit_rect[0]; y = 16*blit_rect[1]; w = 8 *(blit_rect[2]-blit_rect[0]+1); h = 16*(blit_rect[3]-blit_rect[1]+1); y2 = y; if (!is_windowed_mode()) y2 += 40; acquire_screen(); blit(virt_screen, screen, x, y, x, y2, w, h); release_screen(); refresh_needed = 0; memset(blit_rect, 0, 4); } void clearwin(int win) { int h; setwcurs(win, 0, 0); if (win >= WIN_NEXT) clearbox(0, 0, 8, 2); else { clear_bitmap(virt_screen); refresh_needed = 1; } } void setcolorpair(int clr) { int bg; if (clr == PANEL_LABEL_COLOR && !_MONOCHROME) { clr = 3; if (game->mode & MODE_2PLAYER) bg = 4; else { bg = (player1.level % 6)+1; if (bg==6) clr = 7; } clr = bg | clr<<3 | 64; } set_color_pair(clr); } void textgfx_entermenu() { clear_bitmap(virt_screen); margin_x = getmargin_x(); win_y = 1; draw_tetris_logo(0, 0); print_vitetris_ver(19, 4); } void textgfx_entergame() { clearwin(0); margin_x = getmargin_x(); if (!window) win_y = 0; rectfill(screen, 8, SCREEN_H-16, 300, SCREEN_H-1, 0); } vitetris-0.58.0/src/textgfx/ansi.c000066400000000000000000000103761344123051600170410ustar00rootroot00000000000000#include #include #include "textgfx.h" #include "ansivt.h" #include "../input/termin.h" #ifdef NO_BLOCKSTYLES #undef TT_BLOCKS #undef BLACK_BRACKETS #define TT_BLOCKS 0 #define BLACK_BRACKETS 0 #endif unsigned textgfx_flags = ASCII; char curs_x = 0; char curs_y = 0; char margin_x = 0; char menuheight = 1; int win_x = 0; int win_y = 0; void textgfx_init() { set_input_mode(); #ifdef UNIX printf("\033[?25l"); /* hide cursor */ #endif } void textgfx_end() { if (textgfx_flags == 0xFFF) return; setcurs_end(); putch(' '); /* switch back from acs */ restore_input_mode(); printf( #ifdef UNIX "\033[?25h" #endif "\033[m\n"); textgfx_flags = 0xFFF; } static void set_curs(int x, int y) { if (x != curs_x) { if (x > curs_x) printf("\033[%dC", x-curs_x); else printf("\033[%dD", curs_x-x); curs_x = x; } if (y != curs_y) { if (y < curs_y) printf("\033[%dA", curs_y-y); else printf("\033[%dB", y-curs_y); curs_y = y; } } void setcurs(int x, int y) { x += win_x + margin_x; y += win_y; set_curs(x, y); } void movefwd(int n) { printf("\033[%dC", n); curs_x += n; } void newln(int x) { putchar('\n'); x += win_x + margin_x; if (x) printf("\033[%dC", x); #ifndef NO_MENU if (menuheight && curs_x > margin_x+1 && curs_y+1 >= menuheight) menuheight = curs_y+1; #endif curs_x = x; curs_y++; } void setcurs_end() { int y; #ifdef NO_MENU if (0) #else if (menuheight) #endif y = menuheight; else { y = term_height-1; if (y > 20 && y < 23) y = 20; } set_curs(0, y); fflush(stdout); } int is_outside_screen(int x, int y) { return x + win_x + margin_x >= term_width || y + win_y >= term_height; } void get_xy(int *x, int *y) { *x = curs_x - win_x - margin_x; *y = curs_y - win_y; } void refreshscreen() { fflush(stdout); } void cleartoeol() { printf("\033[K"); #ifndef NO_MENU if (curs_x <= margin_x+2 && curs_y < menuheight && curs_y > 4) menuheight = curs_y; #endif } void set_ansi_color(int bg, int fg, char bold) { if (textgfx_flags & BLACK_BRACKETS) { if (bg == fg) { set_ansi_color(-1, fg, '0'); printf("\033[7m"); return; } if (bg >= 0) printf("\033[m"); } if (!_TT_BLOCKS) { if (bg >= 0) printf("\033[4%cm", bg+'0'); else printf("\033[m"); } printf("\033[%c;3%cm", bold, fg+'0'); } void set_color_pair(int clr) { int bg = -1; char bold = '1'; if (_MONOCHROME) { if (clr == MAGENTA_FG) setattr_bold(); return; } switch (clr) { case 7: if (_WHITE_BG) clr = 0; bg = clr; break; case 0x17: printf("\033[m\033[1m"); return; case MAGENTA_FG: clr = 5; break; case WHITE_ON_BLUE: clr = 7; bg = 4; break; case BOARD_BG_COLOR: clr = _WHITE_BG ? 6 : 4; bold = '0'; break; case BOARD_FRAME_COLOR: clr = 4; bold = '0'; break; case RED_FG: clr = 1; break; case YELLOW_ON_BLUE: clr = 3; bg = 4; break; case YELLOW_ON_GREEN: clr = 3; bg = 2; break; default: if (clr & 16) clr &= 7; else bg = clr; } set_ansi_color(bg, clr, bold); } void setattr_normal() { printf("\033[m"); } void setattr_standout() { printf("\033[7m"); } void setattr_bold() { #ifndef NO_BLOCKSTYLES if ((textgfx_flags & TT_MONO) != TT_MONO) #endif printf("\033[1m"); } void setattr_underline() { printf("\033[4m"); } void put_ch(int ch) { static int acs; if (ch < 0) ch = (unsigned char) ch; if (ch == TEXTURE2 && textgfx_flags & (TT_BLOCKS | BLACK_BRACKETS)) ch = ' '|0x100; if (ch & 0x100) { if (_ASCII) { putch_ascii(ch); return; } #if IBMGRAPHICS ch = ibmgfx(ch); #else if (ch == (' '|0x100) || ch == TEXTURE2 && !_LINUX_TERM) ch = ' '; else if (!acs) { printf("\033(0"); acs = 1; } ch &= ~0x100; } else if (acs) { printf("\033(B"); acs = 0; #endif } putchar(ch); curs_x += ch=='\b' ? -1 : 1; } int printstr(const char *str) { int len = strlen(str); int i; if (!len) return 0; if (curs_x+len >= term_width) { len = term_width-curs_x-1; if (len < 1) return 0; } putch(str[0]); for (i = 1; i < len; i++) { putchar(str[i]); curs_x++; } return 1; } void printint(const char *fmt, int d) { putch(' '); putch('\b'); curs_x += printf(fmt, d); } void printlong(const char *fmt, long d) { putch(' '); putch('\b'); curs_x += printf(fmt, d); } int default_bgdot() { return BULLET; } vitetris-0.58.0/src/textgfx/ansi_win.c000066400000000000000000000026361344123051600177160ustar00rootroot00000000000000#include "textgfx.h" #include "ansivt.h" #include "../game/tetris.h" #include "../draw/draw.h" static int window; void setwcurs(int win, int x, int y) { if (win != window) { getwin_xy(win, &win_x, &win_y); window = win; } setcurs(x, y); } void refreshwin(int win) { static int redraw; struct player *p; if (redraw) return; #ifdef TWOPLAYER if ((win == 1 || win == 2) && !game_running) { p = &game->player[win-1]; #else if (win == 1 && !game_running) { p = &player1; #endif redraw = 1; if (game_paused) redrawboard(p, 19); else redrawboard(p, 3); redraw = 0; } refreshscreen(); } /* only used for clearing window showing next tetromino and game screen */ void clearwin(int win) { int h; setwcurs(win, 0, 0); if (win >= WIN_NEXT) clearbox(0, 0, 8, 2); else { margin_x = 0; h = term_height; if (h < 24 && h > 21) h = 21; clearbox(0, 0, 0, h); } } void setcolorpair(int clr) { int bg; if (clr != PANEL_LABEL_COLOR) set_color_pair(clr); else if (!_MONOCHROME) { clr = 3; if (TWOPLAYER_MODE) bg = 4; else { bg = (player1.level % 6)+1; if (bg==6) clr = 7; } set_ansi_color(bg, clr, '1'); } } #ifndef NO_MENU void textgfx_entermenu() { while (curs_y < 4) newln(0); menuheight = 4; margin_x = getmargin_x(); draw_tetris_logo(0, 0); } #endif void textgfx_entergame() { if (menuheight) { menuheight = 0; clearwin(0); margin_x = getmargin_x(); } } vitetris-0.58.0/src/textgfx/ansivt.h000066400000000000000000000004121344123051600174060ustar00rootroot00000000000000extern char curs_x; extern char curs_y; extern char margin_x; extern char menuheight; extern int win_x; extern int win_y; void set_ansi_color(int bg, int fg, char bold); #include "config.h" #if !UNIX || __CYGWIN__ #define IBMGRAPHICS 1 #endif int ibmgfx(int ch); vitetris-0.58.0/src/textgfx/block.c000066400000000000000000000044071344123051600171770ustar00rootroot00000000000000#include #include #include "textgfx.h" #include "../options.h" short block_chars[2] = {TEXTURE1, TEXTURE2}; short bgdot = 0; static void sprint_num(char *s, int i) { #if __STDC_VERSION__ >= 199901L snprintf(s, 3, "%d", i); s[3] = '\0'; #else if (i < 0) { *s = '-'; s++; i = -i; } while (i > 99) i /= 10; if (i > 9) { *s = (i /= 10) + '0'; s++; } s[0] = i+'0'; s[1] = '\0'; #endif } void blockstyle_from_option(const struct option *o) { const char *k = opt_key(o); union val v = o->val; int i; #if !NO_BLOCKSTYLES if (!strcmp(k, "block")) { if (opt_isint(o)) { if (v.integ == -1) { textgfx_flags |= TT_BLOCKS; return; } if (v.integ == -2) { textgfx_flags |= TT_BLOCKS_BG; return; } sprint_num(v.str, v.integ); } for (i = 0; i < 2; i++) { block_chars[i] = isprintable(v.str[i]) ? v.str[i] : ' '; if (v.str[2] == 'a') block_chars[i] |= 0x100; } if (v.str[2] == 'b') textgfx_flags |= BLACK_BRACKETS; } else #endif if (!strcmp(k, "bgdot")) { if (v.str[0] == '~') bgdot = BULLET; else if (isprintable(v.str[0])) bgdot = v.str[0]; else bgdot = ' '; } } static void setblockchars_tt(int clr) { int c = 0; switch (clr) { case 1: block_chars[0] = '<'; block_chars[1] = '>'; break; case 2: c = '%'; break; case 3: c = '#'; break; case 4: block_chars[0] = '['; block_chars[1] = ']'; break; case 5: block_chars[0] = '('; block_chars[1] = ')'; break; case 6: c = '@'; break; case 7: block_chars[0] = '{'; block_chars[1] = '}'; } if (c) { block_chars[0] = c; block_chars[1] = c; } } void setblockcolor(int clr) { if (!clr) { setattr_normal(); if (bgdot != ' ') set_color_pair(BOARD_BG_COLOR); return; } if (!_MONOCHROME) set_color_pair(clr); else #if !NO_BLOCKSTYLES if (!_TT_BLOCKS) #endif { setattr_normal(); setattr_standout(); } #if !NO_BLOCKSTYLES if (textgfx_flags & (TT_BLOCKS | TT_BLOCKS_BG)) setblockchars_tt(clr); #endif } void reset_block_chars() { #if !NO_BLOCKSTYLES if (getopt_int("term", "block")) return; #endif if ((textgfx_flags & (MONOCHROME | ASCII))==MONOCHROME) { block_chars[0] = TEXTURE2; block_chars[1] = TEXTURE1; } else { block_chars[0] = TEXTURE1; block_chars[1] = TEXTURE2; } } vitetris-0.58.0/src/textgfx/curs.h000066400000000000000000000005421344123051600170620ustar00rootroot00000000000000#ifdef NCURSES_VERSION #define COLOR_1_6(i) (i+1) #define COLOR_DEFAULT_BG -1 #else #define COLOR_1_6(i) colors1_6[i] #define COLOR_DEFAULT_BG COLOR_BLACK #endif extern const short colors1_6[6]; extern int margin_x; extern WINDOW *window; extern WINDOW *wins[6]; void init_color_pairs(); void initpair(short pair, short f, short b); void delwins(); vitetris-0.58.0/src/textgfx/curses.c000066400000000000000000000125431344123051600174110ustar00rootroot00000000000000#include #include #include "textgfx.h" #include "curs.h" #include "../input/termin.h" #ifndef NCURSES_VERSION const short colors1_6[6] = { COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN }; #endif unsigned textgfx_flags = 0; int margin_x = 0; WINDOW *window; WINDOW *wins[6] = {NULL}; static chtype acs_chars[17]; void textgfx_init() { if (textgfx_flags & CYGWIN) textgfx_flags |= ASCII; initscr(); set_input_mode(); curs_set(0); if (!_MONOCHROME && start_color() != ERR && COLOR_PAIRS >= 16) { #ifdef NCURSES_VERSION use_default_colors(); #endif init_color_pairs(); } else textgfx_flags |= MONOCHROME; window = stdscr; refresh(); acs_chars[0] = ACS_BOARD; /* h */ acs_chars[2] = ACS_LRCORNER; /* j */ acs_chars[3] = ACS_URCORNER; /* k */ acs_chars[4] = ACS_ULCORNER; /* l */ acs_chars[5] = ACS_LLCORNER; /* m */ acs_chars[6] = ACS_PLUS; /* n */ acs_chars[9] = ACS_HLINE; /* q */ acs_chars[12] = ACS_LTEE; /* t */ acs_chars[13] = ACS_RTEE; /* u */ acs_chars[14] = ACS_BTEE; /* v */ acs_chars[15] = ACS_TTEE; /* w */ acs_chars[16] = ACS_VLINE; /* x */ } void init_color_pairs() { int i; for (i = 0; i < 6; i++) initpair(i+1, COLOR_1_6(i), COLOR_1_6(i)); if (_WHITE_BG) initpair(7, COLOR_BLACK, COLOR_BLACK); else initpair(7, COLOR_WHITE, COLOR_WHITE); init_pair(MAGENTA_FG, COLOR_MAGENTA, COLOR_DEFAULT_BG); initpair(WHITE_ON_BLUE, COLOR_WHITE, COLOR_BLUE); i = _WHITE_BG ? COLOR_CYAN : COLOR_BLUE; init_pair(BOARD_BG_COLOR, i, COLOR_DEFAULT_BG); init_pair(BOARD_FRAME_COLOR, COLOR_BLUE, COLOR_DEFAULT_BG); init_pair(RED_FG, COLOR_RED, COLOR_DEFAULT_BG); if (!(textgfx_flags & (TT_BLOCKS | BLACK_BRACKETS))) { init_pair(15, COLOR_GREEN, COLOR_DEFAULT_BG); init_pair(16, COLOR_YELLOW, COLOR_DEFAULT_BG); init_pair(17, COLOR_CYAN, COLOR_DEFAULT_BG); } } void initpair(short pair, short f, short b) { if (_TT_BLOCKS || f==b && textgfx_flags & BLACK_BRACKETS) b = COLOR_DEFAULT_BG; init_pair(pair, f, b); } void textgfx_end() { int x, y; delwins(); if (!isendwin()) { getmaxyx(stdscr, y, x); move(y-1, 0); clrtobot(); refresh(); endwin(); } } void delwins() { int i; for (i = 0; i < 6; i++) if (wins[i]) { delwin(wins[i]); wins[i] = NULL; } } void setcurs(int x, int y) { if (window == stdscr) x += margin_x; else if (x < 0) { margin_x = x; x = 0; } else margin_x = 0; wmove(window, y, x); } void movefwd(int n) { int x, y; getyx(window, y, x); x += n; if (margin_x < 0) setcurs(x+margin_x, y); else wmove(window, y, x); } void newln(int x) { int d, y; getyx(window, y, d); setcurs(x, y+1); } void setcurs_end() { move(term_height-1, 0); refresh(); window = stdscr; } int is_outside_screen(int x, int y) { int xmax, ymax; if (window == stdscr) x += margin_x; getmaxyx(window, ymax, xmax); return x >= xmax || y >= ymax; } void get_xy(int *x, int *y) { getyx(window, *y, *x); } void cleartoeol() { wclrtoeol(window); } static void setfgcolor(int clr) { int pairs[6] = {RED_FG, 15, 16, BOARD_FRAME_COLOR, MAGENTA_FG, 17}; int attrs = A_BOLD; clr &= 7; if (textgfx_flags & (TT_BLOCKS | BLACK_BRACKETS)) attrs |= COLOR_PAIR(clr); else attrs |= COLOR_PAIR(pairs[clr-1]); wattrset(window, attrs); } void set_color_pair(int pair) { int attrs; if (_MONOCHROME) { if (pair == MAGENTA_FG) setattr_bold(); return; } if (pair == YELLOW_ON_BLUE) { initpair(YELLOW_ON_GREEN, COLOR_YELLOW, COLOR_BLUE); pair = YELLOW_ON_GREEN; } else if (pair == YELLOW_ON_GREEN) initpair(YELLOW_ON_GREEN, COLOR_YELLOW, COLOR_GREEN); else if (pair & 16) { setfgcolor(pair); return; } attrs = COLOR_PAIR(pair); switch (pair) { case 0: case BOARD_BG_COLOR: case BOARD_FRAME_COLOR: break; case PANEL_LABEL_COLOR: attrs |= A_BOLD; break; case RED_FG: if (_WHITE_BG) break; default: if (pair <= 7 && textgfx_flags & BLACK_BRACKETS) attrs |= A_REVERSE; else attrs |= A_BOLD; } wattrset(window, attrs); } void setattr_normal() { wattrset(window, A_NORMAL); } void setattr_standout() { wstandout(window); } void setattr_bold() { if ((textgfx_flags & TT_MONO) != TT_MONO) wattron(window, A_BOLD); } void setattr_underline() { wattron(window, A_UNDERLINE); } static int putch_acs1(int ch) { chtype c; switch (ch) { case TEXTURE1: c = ACS_CKBOARD; break; case BULLET: c = ACS_BULLET; break; case UPARROW: c = ACS_UARROW; break; default: return 0; } waddch(window, c); return 1; } static int putch_acs(int ch) { int x, y; int i; if (putch_acs1(ch)) return 1; if (ch >= TEXTURE2 && ch <= VLINE) { i = ch-0x100-'h'; if (acs_chars[i]) { getyx(window, y, x); waddch(window, acs_chars[i]); if (is_outside_screen(x+1, 0)) wmove(window, y, x); return 1; } } return 0; } void put_ch(int ch) { if (!(ch & 0x100)) waddch(window, ch); else if (_ASCII || ch == (' '|0x100) || ch == TEXTURE2 && textgfx_flags & (XTERM | TT_BLOCKS | BLACK_BRACKETS)) putch_ascii(ch); else if (!putch_acs(ch)) waddch(window, ch & ~0x100); } int printstr(const char *str) { int x, y, w; int n = strlen(str); getyx(window, y, x); getmaxyx(window, y, w); if (x+n >= w) n = w-x-1; waddnstr(window, str, n); return n; } void printint(const char *fmt, int d) { wprintw(window, fmt, d); } void printlong(const char *fmt, long d) { wprintw(window, fmt, d); } int default_bgdot() { return _XTERM ? BULLET : '.'; } vitetris-0.58.0/src/textgfx/curses_win.c000066400000000000000000000047731344123051600202740ustar00rootroot00000000000000#include #include "textgfx.h" #include "curs.h" #include "../game/tetris.h" #include "../draw/draw.h" static int winindex(int win) { switch (win) { case WIN_TETROM_STATS: return 2; case WIN_TOP_SCORES: return 4; } return win; } static void clearboard_paused_fix() { #ifdef PDCURSES int x = board_x(1, 0); int i; setcurs(x, _HEIGHT_24L ? 4 : 0); for (i=0; i < 20; i++) { putnchars('/', 20); if (i < 19) newln(x); } refresh(); #endif } void setwcurs(int win, int x, int y) { window = wins[winindex(win)]; if (!window) { window = stdscr; margin_x = getmargin_x(); if (game && game_paused && y <= 4) clearboard_paused_fix(); } setcurs(x, y); } void refreshwin(int i) { WINDOW *win; if (i == -1) win = window; else win = wins[winindex(i)]; if ((i==1 || i==2) && !game_running) { #ifdef PDCURSES print_game_message(i, " ", 0); #endif touchwin(win); } if (win) wrefresh(win); else { attrset(A_NORMAL); refresh(); } } void clearwin(int win) { setwcurs(win, 0, 0); werase(window); } static int set_panel_label_color() { short f = COLOR_YELLOW; short b; if (TWOPLAYER_MODE) b = COLOR_BLUE; else { b = COLOR_1_6(player1.level % 6); if (b == COLOR_CYAN) f = COLOR_WHITE; if (b == COLOR_YELLOW) return 3; } initpair(PANEL_LABEL_COLOR, f, b); return PANEL_LABEL_COLOR; } void setcolorpair(int pair) { if (pair == PANEL_LABEL_COLOR) pair = set_panel_label_color(); set_color_pair(pair); } #ifndef NO_MENU void textgfx_entermenu() { int x = getmargin_x(); delwins(); refresh(); window = newwin(term_height-1, term_width-x, 1, x); wins[0] = window; draw_tetris_logo(0, 0); print_vitetris_ver(19, 4); } static void print_ver_author() { int y; if (_HEIGHT_24L && margin_x > 14) { window = stdscr; attrset(A_NORMAL); print_vitetris_ver(-margin_x, 0); } } #endif static void createwin(int i, int w, int h) { int x, y; getwin_xy(i, &x, &y); i = winindex(i); wins[i] = newwin(h, w, y, x+margin_x); } void textgfx_entergame() { delwins(); margin_x = getmargin_x(); createwin(1, 20, 20); if (!TWOPLAYER_MODE) { createwin(WIN_NEXT, 8, 2); createwin(WIN_PANEL, 10, 20); if (term_width >= 45) { createwin(WIN_TETROM_STATS, 9, 9); if (term_width >= 47) createwin(WIN_TOP_SCORES, 11, 7); } } else { createwin(2, 20, 20); if (_HEIGHT_24L || term_width >= 76) { createwin(WIN_NEXT, 8, 2); createwin(WIN_NEXT+1, 8, 2); } createwin(WIN_PANEL, 12, 20); } clear(); #ifndef NO_MENU print_ver_author(); #endif } vitetris-0.58.0/src/textgfx/ibmgfx.c000066400000000000000000000004521344123051600173550ustar00rootroot00000000000000#include int ibmgfx(int ch) { const char *vt100 = "lmkjnqxtuvwah~-"; const char *cp437 = "\xDA\xC0\xBF\xD9\xC5\xC4\xB3" "\xC3\xB4\xC1\xC2\xB1\xB0\xFA\x18"; char *p; if (ch & 0x100) { ch ^= 0x100; p = strchr(vt100, ch); if (p) return cp437[p-vt100]; } return ch; } vitetris-0.58.0/src/textgfx/print.c000066400000000000000000000014751344123051600172430ustar00rootroot00000000000000#include #include "textgfx.h" #include "../lang.h" void putch_ascii(int ch) { switch (ch) { case HLINE: ch = '-'; break; case VLINE: ch = '|'; break; case TEXTURE1: ch = '#'; break; case TEXTURE2: case ' '|0x100: ch = ' '; break; case BULLET: ch = '.'; break; case UPARROW: ch = '^'; break; default: ch = '+'; } putch(ch); } int putnchars(int ch, int n) { int i = 0; for (; i < n; i++) putch(ch); return n; } void printstr_acs(const char *str, int n) { int ch = 0; while (*str) { if (islower(*str) || (ch & 0x100) && *str == ' ') ch = *str | 0x100; else ch = *str; putch(ch); str++; if (*str == 'N') { putnchars(ch, n-1); str++; } } } int isprintable(int c) { return c >= ' ' && c < 0x7F || lang & LATIN1 && (unsigned char) c >= 0xA0; } vitetris-0.58.0/src/textgfx/resize.c000066400000000000000000000053221344123051600174030ustar00rootroot00000000000000#include #include "textgfx.h" #if !SIGWINCH void enable_term_resizing() {} void upd_termresize() {} #else #ifdef CURSES #include #include "curs.h" #else #include "ansivt.h" /* menuheight */ #endif #include "../game/tetris.h" #include "../draw/draw.h" #include "../netw/sock.h" static void resizehandler(int sig) { textgfx_flags |= TERM_RESIZED; } void enable_term_resizing() { signal(SIGWINCH, resizehandler); } static void entergame_redraw() { #ifndef CURSES menuheight = 1; #endif textgfx_entergame(); if (!TWOPLAYER_MODE) drawgamescreen_1p(); else drawgamescreen_2p(); if (game->next) { refreshwin(0); print_press_key(); } #ifdef SOCKET if (game->mode & MODE_NETWORK && CONNECTED != (sock_flags & (CONNECTED | WAIT_PL2INGAME))) print_game_message(1, "WAIT", 1); #endif } #if CURSES && KEY_RESIZE static void resizemenu(int w, int h) { int x, y; if (h > term_height) { getyx(window, y, x); wmove(window, term_height-2, 0); wclrtobot(window); wmove(window, y, x); } x = getmargin_x(); if (w > term_width) mvwin(window, 1, x); resizeterm(term_height, term_width); wresize(window, term_height-1, term_width-x); if (w < term_width) mvwin(window, 1, x); clear(); refresh(); touchwin(window); wrefresh(window); } static void resizegamerunning() { WINDOW *next = wins[WIN_NEXT]; WINDOW *next2 = NULL; int i, x, y; wins[WIN_NEXT] = NULL; if (TWOPLAYER_MODE) { next2 = wins[WIN_NEXT+1]; wins[WIN_NEXT+1] = NULL; } entergame_redraw(); touchwin(wins[1]); wrefresh(wins[1]); if (TWOPLAYER_MODE) { touchwin(wins[2]); wrefresh(wins[2]); } if (!next) return; i = WIN_NEXT; while (1) { getwin_xy(i, &x, &y); x += getmargin_x(); mvwin(next, y, x); overlay(next, wins[i]); delwin(next); wrefresh(wins[i]); if (TWOPLAYER_MODE && next != next2) { next = next2; i++; continue; } break; } } #endif void upd_termresize() { #if !CURSES || KEY_RESIZE int w, h; if (!(textgfx_flags & TERM_RESIZED) || !in_menu && game && game->state & (GAME_OVER # ifndef CURSES | GAME_RUNNING # endif )) return; textgfx_flags &= ~TERM_RESIZED; w = term_width; h = term_height; gettermsize(); # ifndef CURSES if (w == term_width && h == term_height) return; if (in_menu) return; # else if (in_menu) { resizemenu(w, h); return; } resizeterm(term_height, term_width); if (game && game_running) { resizegamerunning(); return; } # endif entergame_redraw(); # ifndef CURSES if (term_height < 24 && term_height > 21) { w = -getmargin_x(); setwcurs(0, -w, 20); newln(-w); clearbox(w, 21, 0, term_height-21); } # endif drawnext(&player1, game->next); if (TWOPLAYER_MODE) drawnext(&player2, game->next); #endif } #endif /* SIGWINCH */ vitetris-0.58.0/src/textgfx/term.c000066400000000000000000000044611344123051600170540ustar00rootroot00000000000000#include #include #include #include "../config.h" #if HAVE_GETTEXTINFO #include #define conio_h #elif UNIX #include #include #endif #include "textgfx.h" #include "../options.h" char term_width = 80; char term_height = 20; void blockstyle_from_option(const struct option *o); static int gettermsize_unix() { #if defined(TIOCGSIZE) struct ttysize tty; if (!ioctl(STDIN_FILENO, TIOCGSIZE, &tty)) { settermwidth (tty.ts_cols); settermheight(tty.ts_lines); return 1; } #elif defined(TIOCGWINSZ) struct winsize win; if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &win)) { settermwidth (win.ws_col); settermheight(win.ws_row); return 1; } #endif return 0; } void gettermsize() { char *s; int w = 80; int h = 25; #if HAVE_GETTEXTINFO struct text_info text; gettextinfo(&text); w = text.screenwidth; h = text.screenheight; #endif if (gettermsize_unix()) return; if (s = getenv("COLUMNS")) w = atoi(s); if (s = getenv("LINES")) h = atoi(s); settermwidth(w); settermheight(h); } void settermwidth(int w) { if (w < 32) w = 32; else if (w > 127) w = 127; term_width = w; } void settermheight(int h) { if (h < 20) h = 20; else if (h > 25) h = 25; term_height = h; if (term_height < 24) textgfx_flags &= ~HEIGHT_24L; else textgfx_flags |= HEIGHT_24L; } static void gettermenv() { #if UNIX char *s = getenv("TERM"); if (s) { if (!strncmp(s, "xterm", 5)) textgfx_flags |= XTERM; else if (!strcmp(s, "linux")) textgfx_flags |= LINUX_TERM; else if (!strcmp(s, "cygwin")) textgfx_flags |= CYGWIN; } s = getenv("COLORTERM"); if (s && !strcmp(s, "gnome-terminal")) textgfx_flags |= GNOME_TERM; #endif } void gettermoptions() { struct option *o; char *k; union val v; gettermenv(); o = getoptions("term"); for (; o; o = o->next) { k = opt_key(o); v = o->val; if (!strcmp(k, "bg")) { if (v.integ == 1) textgfx_flags |= WHITE_BG; } else if (!strcmp(k, "drawing")) { if (v.integ) textgfx_flags |= ASCII; else textgfx_flags &= ~ASCII; } else if (!strcmp(k, "color")) { if (!v.integ) textgfx_flags |= MONOCHROME; } else blockstyle_from_option(o); } if ((textgfx_flags & (WHITE_BG | TT_MONO))==(WHITE_BG | TT_BLOCKS)) textgfx_flags ^= TT_BLOCKS | TT_BLOCKS_BG; reset_block_chars(); } vitetris-0.58.0/src/textgfx/textgfx.h000066400000000000000000000070071344123051600176020ustar00rootroot00000000000000/* * textgfx flags */ #define ASCII 1 #define WHITE_BG 2 #define MONOCHROME 4 #define HEIGHT_24L 8 /* block styles */ #define BLACK_BRACKETS 16 #define TT_BLOCKS 32 #define TT_BLOCKS_BG 64 #define XTERM 0x80 #define LINUX_TERM 0x100 #define GNOME_TERM 0x200 #define CYGWIN 0x400 #define TERM_RESIZED 0x800 #define LOST_FOCUS 0x1000 extern unsigned textgfx_flags; #define _ASCII (textgfx_flags & ASCII) #define _WHITE_BG (textgfx_flags & WHITE_BG) #define _MONOCHROME (textgfx_flags & MONOCHROME) #define _HEIGHT_24L (textgfx_flags & HEIGHT_24L) #define _TT_BLOCKS (textgfx_flags & TT_BLOCKS) #define _TT_BLOCKS_BG (textgfx_flags & TT_BLOCKS_BG) #define TT_MONO (TT_BLOCKS | MONOCHROME) #define _XTERM (textgfx_flags & XTERM) #define _LINUX_TERM (textgfx_flags & LINUX_TERM) extern char term_width; extern char term_height; extern short block_chars[2]; extern short bgdot; int default_bgdot(); void reset_block_chars(); void gettermsize(); void settermwidth(int cols); void settermheight(int lines); void gettermoptions(); void textgfx_init(); void textgfx_end(); #ifdef NO_MENU #define in_menu 0 #define textgfx_entermenu() #else extern int in_menu; void textgfx_entermenu(); #endif void textgfx_entergame(); /* Windows 0 - standard screen 1 - board 1 2 - board 2 */ #define WIN_NEXT 3 /* WIN_NEXT+1 - player 2's next */ #define WIN_PANEL 5 #define WIN_TETROM_STATS 6 #define WIN_TOP_SCORES 7 int getmargin_x(); void getwin_xy(int win, int *x, int *y); void setcurs(int x, int y); void setwcurs(int win, int x, int y); void movefwd(int n); void newln(int x); void setcurs_end(); int is_outside_screen(int x, int y); void get_xy(int *x, int *y); void refreshscreen(); /* refreshwin(-1) refreshes the current window */ void refreshwin(int win); void clearwin(int win); void cleartoeol(); /* Color pairs. * 1-7 are used for blocks. * 0x11-0x17 are block colors without bg. */ #define MAGENTA_FG 8 #define WHITE_ON_BLUE 9 #define BOARD_BG_COLOR 10 #define BOARD_FRAME_COLOR 11 #define PANEL_LABEL_COLOR 12 #define RED_FG 13 #define YELLOW_ON_GREEN 14 #define YELLOW_ON_BLUE 0x18 void setcolorpair(int pair); /* inner func - doesn't set PANEL_LABEL_COLOR which depends on tetris level */ void set_color_pair(int pair); /* Set color pair and block chars based on block style. * clr = 1-7 or 0 for board bg. */ void setblockcolor(int clr); void setattr_normal(); void setattr_standout(); void setattr_bold(); void setattr_underline(); /* Line drawing characters - used with putch */ #define UPLEFT ('l' | 0x100) #define LOWLEFT ('m' | 0x100) #define UPRIGHT ('k' | 0x100) #define LOWRIGHT ('j' | 0x100) #define CROSSLINES ('n' | 0x100) #define HLINE ('q' | 0x100) #define VLINE ('x' | 0x100) #define LEFT_T ('t' | 0x100) #define RIGHT_T ('u' | 0x100) #define BOTTOM_T ('v' | 0x100) #define TOP_T ('w' | 0x100) #define TEXTURE1 ('a' | 0x100) /* ACS_CKBOARD */ #define TEXTURE2 ('h' | 0x100) /* ACS_BOARD or blank */ #define BULLET ('~' | 0x100) #define UPARROW ('-' | 0x100) /* putch conflicts with DOS conio */ void put_ch(int ch); #ifndef conio_h #define putch(ch) put_ch(ch) #endif int printstr(const char *str); void printint(const char *fmt, int d); void printlong(const char *fmt, long d); /* takes a line drawing character and prints ascii */ void putch_ascii(int ch); int putnchars(int ch, int n); /* prints lowercase letters in str using alternate character set, * and repeats a character followed by 'N' n times */ void printstr_acs(const char *str, int n); int isprintable(int c); void enable_term_resizing(); void upd_termresize(); vitetris-0.58.0/src/textgfx/win.c000066400000000000000000000014571344123051600167040ustar00rootroot00000000000000#include "textgfx.h" #include "../draw/draw.h" #include "../game/tetris.h" #if !NO_MENU int in_menu = 1; #endif int getmargin_x() { int x; if (term_width <= 32) x = 0; else if (!in_menu && TWOPLAYER_MODE) { if (term_width < 58) x = 0; else x = (term_width-56)/2; } else if (term_width < 48) x = 1; else x = (term_width-(in_menu ? 34 : 44))/2; return x; } void getwin_xy(int win, int *x, int *y) { *y = 0; switch (win) { case 0: *x = 0; return; case 1: case 2: *x = board_x(win, 0); break; case WIN_NEXT: case WIN_NEXT+1: next_xy(1+win-WIN_NEXT, x, y); return; case WIN_PANEL: *x = TWOPLAYER_MODE ? 22 : 0; break; case WIN_TETROM_STATS: *y = 11; case WIN_TOP_SCORES: *x = board_x(1, 12); if (!*y && !_HEIGHT_24L) *y = 1; } if (_HEIGHT_24L) *y += 4; } vitetris-0.58.0/src/timer.c000066400000000000000000000026631344123051600155360ustar00rootroot00000000000000#include "config.h" #if UNIX #include #include #elif WIN32 #include #include #elif PCTIMER #include "pctimer.h" #elif ALLEGRO #include #else #include #include #endif #include "timer.h" #ifdef ALLEGRO_VERSION static volatile unsigned long elapsed_tm; static void inc_tm() { elapsed_tm++; } END_OF_FUNCTION(inc_tm) #endif void timer_init() { #if WIN32 timeBeginPeriod(1); /* sleep just 1 millisecond */ #elif PCTIMER pctimer_init(1000); #endif } void timer_end() { #if WIN32 timeEndPeriod(1); #elif PCTIMER pctimer_exit(); #endif } int gettm(int a) { int b; #if UNIX struct timeval tmv; gettimeofday(&tmv, NULL); b = 1000*(tmv.tv_sec % 10) + tmv.tv_usec/1000; #elif WIN32 long ms = timeGetTime(); b = ms % 10000; #elif PCTIMER unsigned long ms = pctimer_time(0, pctimer_get_ticks()); b = ms % 10000; #elif ALLEGRO if (!elapsed_tm) { elapsed_tm = 1; install_int(inc_tm, 1); } b = elapsed_tm % 10000; #elif UCLOCKS_PER_SEC uclock_t ms = uclock() / (UCLOCKS_PER_SEC/1000); b = ms % 10000; #else clock_t hs = clock() / (CLOCKS_PER_SEC/100.0); b = 10*(hs % 1000); #endif b++; while (b < a) b += 10000; return b; } void sleep_msec(unsigned ms) { #if UNIX usleep(1000*ms); #elif WIN32 Sleep(ms); #elif PCTIMER pctimer_sleep(ms); #elif ALLEGRO if (!elapsed_tm) { elapsed_tm = 1; install_int(inc_tm, 1); } rest(ms); #else delay(ms); #endif } vitetris-0.58.0/src/timer.h000066400000000000000000000003271344123051600155360ustar00rootroot00000000000000#ifndef CLOCKS_PER_SEC #define CLOCKS_PER_SEC CLK_TCK #endif void timer_init(); void timer_end(); /* get time in milliseconds >= tm */ int gettm(int tm); /* sleep ms milliseconds */ void sleep_msec(unsigned ms); vitetris-0.58.0/src/version.h000066400000000000000000000001501344123051600160750ustar00rootroot00000000000000#define VERSION_NO "0.58.0" #define VERSION_DATE "20190310" #define VITETRIS_VER "vitetris "VERSION_NO vitetris-0.58.0/vitetris.desktop000066400000000000000000000002451344123051600167210ustar00rootroot00000000000000[Desktop Entry] Type=Application Encoding=UTF-8 Name=vitetris GenericName=Text-mode Tetris Exec=tetris -w 80 Icon=vitetris Categories=Game;BlocksGame; Terminal=true vitetris-0.58.0/vitetris.xpm000066400000000000000000000050371344123051600160600ustar00rootroot00000000000000/* XPM */ static char * icon_xpm[] = { "48 48 3 1", " c None", ". c #AA0000", "+ c #FF5555", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", ".+.+.+.+...+...+.+.+.+.+...+...+.+.+.+.+...+...+", "+.+.+.+..+...+..+.+.+.+..+...+..+.+.+.+..+...+..", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. ", " .+.+.+.+...+...+ ", " +.+.+.+..+...+.. "};