diff options
author | culot <culot@FreeBSD.org> | 2018-07-27 11:22:11 +0200 |
---|---|---|
committer | culot <culot@FreeBSD.org> | 2018-07-27 11:22:11 +0200 |
commit | 2b3b9dc4649727851004b8223b6af38b57c0c790 (patch) | |
tree | 418867a8ac458e7b0a7fcaca90b551628a8e6810 | |
download | oldrunner-2b3b9dc4649727851004b8223b6af38b57c0c790.tar.gz |
oldrunner initial import
-rw-r--r-- | ChangeLog | 20 | ||||
-rw-r--r-- | GNUmakefile | 65 | ||||
-rw-r--r-- | README | 21 | ||||
-rw-r--r-- | TODO | 13 | ||||
-rw-r--r-- | bricks.c | 169 | ||||
-rw-r--r-- | cfg.h | 61 | ||||
-rw-r--r-- | compat.h | 56 | ||||
-rw-r--r-- | compat/fgetln.c | 86 | ||||
-rw-r--r-- | compat/queue.h | 527 | ||||
-rw-r--r-- | compat/strtonum.c | 65 | ||||
-rwxr-xr-x | configure | 78 | ||||
-rw-r--r-- | coord.c | 117 | ||||
-rw-r--r-- | foes.c | 290 | ||||
-rw-r--r-- | game.c | 297 | ||||
-rw-r--r-- | gfx.c | 448 | ||||
-rw-r--r-- | hero.c | 188 | ||||
-rw-r--r-- | io.c | 86 | ||||
-rw-r--r-- | levels/original.lvl | 3155 | ||||
-rw-r--r-- | lvl.c | 602 | ||||
-rw-r--r-- | mem.c | 96 | ||||
-rw-r--r-- | money.c | 100 | ||||
-rwxr-xr-x | oldrunner.6 | 102 | ||||
-rw-r--r-- | oldrunner.c | 86 | ||||
-rw-r--r-- | oldrunner.h | 282 | ||||
-rw-r--r-- | timer.c | 95 | ||||
-rw-r--r-- | usr.c | 113 |
26 files changed, 7218 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..bf31bb8 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,20 @@ +2012-01-31 Frederic Culot <frederic@culot.org> + + * Fix a display issue which caused part of the game board to be + hidden on wide screens. + + * Fix an erroneous check which could lead to an out of bounds + access on the curlvl->lay array. + +2012-01-06 Frederic Culot <frederic@culot.org> + + * Fix the sprite enum to avoid indexes past the end of arrays such + as with the SP_INVALID element in sprites_init(). + +2010-07-17 Frederic Culot <frederic@culot.org> + + * first public release + +2010-04-01 Frederic Culot <frederic@culot.org> + + * beginning of the project diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 0000000..07ed10c --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,65 @@ +# $Id: GNUmakefile,v 1.4 2012/01/06 10:13:55 culot Exp $ + +VERSION= 20120131 + +PRJ= $(shell basename `pwd`) +EXE= $(PRJ) +BAK= $(PRJ)-$(shell date '+%Y%m%d-%H%M').tar.gz +PKG= $(PRJ)-$(VERSION).tar.gz +SRCDIR= ./ + +CC?= gcc +CFLAGS+= -Wall -DVERSION="\"$(VERSION)\"" +LDFLAGS+= +LIBS+= + +#FDEBUG= 1 + +ifdef FDEBUG +CFLAGS+= -g -ggdb -DDEBUG +endif + +SRCS= $(wildcard $(SRCDIR)/*.c) +-include config.mk +OBJ= $(SRCS:.c=.o) + + +all: $(EXE) + +$(EXE): $(OBJ) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +%.o: %.c + $(CC) $(CFLAGS) -o $@ -c $< + +backup: clean-all + @cd .. && tar czvf $(BAK) $(PRJ) >/dev/null && mv $(BAK) $(PRJ) + @echo "==> Backup created: $(BAK)" + +dist: clean-all + @cd .. && tar -czvf $(PKG) --exclude='CVS' $(PRJ) >/dev/null && mv $(PKG) $(PRJ) + @echo "==> Package created: $(PKG)" + +clean-all: clean + @rm -f config.mk config.h TAGS + +clean: + @rm -f $(OBJ) $(EXE) + @rm -f core + @rm -f *.gz + @echo "==> Project cleaned" + +tags: + @etags *.[ch] + @echo "==> Tags generated" + +count: + @wc -l *.[ch] + +list-todo: + @grep -n XXX *.[ch] + +list-targets: + @cat GNUmakefile | grep -E ^[^[:space:]\.$$%]+: | cut -d: -f1 + +.PHONY: all backup dist clean clean-all tags count list-todo list-targets @@ -0,0 +1,21 @@ +Oldrunner is a text-mode remake of the Loadrunner game from Broderbund and +contains the 150 original game levels. See the manpage for more information. + +INSTALL + To compile oldrunner, first run the configure script and then compile the + game using 'gmake' or 'make' depending on your system. + +LICENSE + The game is released under the BSD License. The original game levels are + copyright (c)1994 Presage Software Development Co.; all rights reserved. + +THANKS + Thanks go to: + + * Joshua Neal for the 'lodetool' software which allowed the convertion of + the original game levels to human-readable ascii ones. + + * Nicholas Marriott for the tmux configuration script which greatly inspired + the configure script distributed with oldrunner. + + @@ -0,0 +1,13 @@ + + oldrunner TODO list + ------------------- + +Here are listed the modifications I should perform on loderunner in future +releases. Feel free to send me an email/patch (frederic@culot.org) if you +would like to see a feature added. + + + * Add a command-line flag to set game difficulty (acting on FOES_DELAY, BRICK_LATENCY...) + * Add support for high-scores recording + * Allow user to pause the game + * Make it possible to load user-created levels diff --git a/bricks.c b/bricks.c new file mode 100644 index 0000000..3060c21 --- /dev/null +++ b/bricks.c @@ -0,0 +1,169 @@ +/* $Id: bricks.c,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "oldrunner.h" + +#define BRICK_LATENCY (OLDRUNNER_TIMEOUT * 4) + +enum brick_state { + BRICK_SMALL_CRACK, + BRICK_LARGE_CRACK, + BRICK_BROKEN, + BRICK_COMEBACK_LARGE_CRACK, + BRICK_COMEBACK_SMALL_CRACK, + BRICK_REBUILT, + BRICK_STATES +}; + +struct brick { + enum brick_state state; + struct timer timer; + struct coord pos; + SLIST_ENTRY(brick) bricksp; +}; + +SLIST_HEAD(, brick) bricks; + +void +bricks_init (void) +{ + SLIST_INIT (&bricks); +} + +void +bricks_free (void) +{ + while (!SLIST_EMPTY (&bricks)) + { + struct brick *b; + + b = SLIST_FIRST (&bricks); + SLIST_REMOVE_HEAD (&bricks, bricksp); + xfree (b); + } +} + +void +bricks_break (const struct coord *pos) +{ + struct brick *b; + + b = xmalloc (sizeof *b); + coord_set_yx (&b->pos, pos->y, pos->x); + b->state = BRICK_SMALL_CRACK; + timer_start (&b->timer); + SLIST_INSERT_HEAD (&bricks, b, bricksp); +} + +static void +draw_brick (const struct coord *pos, enum brick_state state) +{ + switch (state) + { + case BRICK_SMALL_CRACK: + case BRICK_COMEBACK_SMALL_CRACK: + gfx_show_sprite (SP_BRICK_SCRACK, pos); + break; + case BRICK_LARGE_CRACK: + case BRICK_COMEBACK_LARGE_CRACK: + gfx_show_sprite (SP_BRICK_LCRACK, pos); + break; + case BRICK_BROKEN: + if (hero_at_pos (pos)) + gfx_show_sprite (SP_HERO, pos); + else if (foes_at_pos (pos)) + gfx_show_sprite (SP_FOE, pos); + else + gfx_show_sprite (SP_BRICK_BROKEN, pos); + break; + case BRICK_REBUILT: + gfx_show_sprite (SP_BRICK, pos); + break; + default: + return; + /* NOTREACHED */ + } +} + +void +bricks_draw (void) +{ + struct brick *b; + + SLIST_FOREACH (b, &bricks, bricksp) + draw_brick (&b->pos, b->state); +} + +unsigned +bricks_broken_at (const struct coord *pos) +{ + struct brick *b; + + SLIST_FOREACH (b, &bricks, bricksp) + { + if (b->state == BRICK_BROKEN && coord_equal (&b->pos, pos)) + return 1; + } + + return 0; +} + +void +bricks_update (void) +{ + struct brick *b; + struct timer now; + + timer_get_time (&now); + SLIST_FOREACH (b, &bricks, bricksp) + { + double difftot; + + difftot = timer_diff (&now, &b->timer); + if (difftot > BRICK_LATENCY) + { + timer_set (&now, &b->timer); + b->state++; + if (b->state == BRICK_BROKEN) + { + hero_dig_done (); + timer_add (&b->timer, BRICK_COMEBACK_TIME); + } + else if (b->state > BRICK_REBUILT) + { + foes_wallup_at (&b->pos); + if (!hero_wallup_at (&b->pos)) + SLIST_REMOVE (&bricks, b, brick, bricksp); + } + } + } +} @@ -0,0 +1,61 @@ +/* $Id: cfg.h,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define CTRLVAL 0x1F +#define CTRL(x) ((x) & CTRLVAL) + +/* + * User-definable variables are defined below. + * Update configuration to suit your needs and then recompile. + */ + +/* User keys. */ +#define ORKEY_MOVE_RIGHT 'l' +#define ORKEY_MOVE_LEFT 'h' +#define ORKEY_MOVE_DOWN 'j' +#define ORKEY_MOVE_UP 'k' +#define ORKEY_DIG_LEFT 's' +#define ORKEY_DIG_RIGHT 'd' +#define ORKEY_LEVEL_NEXT CTRL('n') +#define ORKEY_LEVEL_PREV CTRL('p') +#define ORKEY_SUICIDE CTRL('g') +#define ORKEY_EXIT CTRL('d') + +/* To set game speed (timeout in microseconds). */ +#define OLDRUNNER_TIMEOUT 80000 + +/* + * If game levels files are installed in a system-wide location, set the + * LEVELS_PATH symbol to the appropriate path, such as: + * + * #define LEVELS_PATH "/usr/local/share/games/oldrunner/levels" + */ diff --git a/compat.h b/compat.h new file mode 100644 index 0000000..f8aec7f --- /dev/null +++ b/compat.h @@ -0,0 +1,56 @@ +/* $Id: compat.h,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef COMPAT_H +#define COMPAT_H + +#ifdef HAVE_QUEUE_H +# include <sys/queue.h> +#else +# include "compat/queue.h" +#endif + +#ifndef HAVE_BZERO +# define bzero(buf, len) memset ((buf), 0, (len)); +#endif + +#ifndef HAVE_STRTONUM +/* strtonum.c */ +long long strtonum (const char *, long long, long long, const char **); +#endif + +#ifndef HAVE_FGETLN +/* fgetln.c */ +char *fgetln (FILE *, size_t *); +#endif + +#endif /* COMPAT_H */ diff --git a/compat/fgetln.c b/compat/fgetln.c new file mode 100644 index 0000000..432677b --- /dev/null +++ b/compat/fgetln.c @@ -0,0 +1,86 @@ +/* $NetBSD: fgetln.c,v 1.3 2007/08/07 02:06:58 lukem Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +char * +fgetln(fp, len) + FILE *fp; + size_t *len; +{ + static char *buf = NULL; + static size_t bufsiz = 0; + char *ptr; + + + if (buf == NULL) { + bufsiz = BUFSIZ; + if ((buf = malloc(bufsiz)) == NULL) + return NULL; + } + + if (fgets(buf, bufsiz, fp) == NULL) + return NULL; + + *len = 0; + while ((ptr = strchr(&buf[*len], '\n')) == NULL) { + size_t nbufsiz = bufsiz + BUFSIZ; + char *nbuf = realloc(buf, nbufsiz); + + if (nbuf == NULL) { + int oerrno = errno; + free(buf); + errno = oerrno; + buf = NULL; + return NULL; + } else + buf = nbuf; + + *len = bufsiz; + if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL) + return buf; + + bufsiz = nbufsiz; + } + + *len = (ptr - buf) + 1; + return buf; +} + diff --git a/compat/queue.h b/compat/queue.h new file mode 100644 index 0000000..a6fe39c --- /dev/null +++ b/compat/queue.h @@ -0,0 +1,527 @@ +/* $OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +#ifdef QUEUE_MACRO_DEBUG +#define _Q_INVALIDATE(a) (a) = ((void *)-1) +#else +#define _Q_INVALIDATE(a) +#endif + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != SLIST_END(head); \ + (varp) = &SLIST_NEXT((var), field)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \ + SLIST_FIRST(head) = SLIST_END(head); \ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define SLIST_REMOVE_NEXT(head, elm, field) do { \ + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->slh_first; \ + \ + while (curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + _Q_INVALIDATE((elm)->field.sle_next); \ + } \ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for((var) = LIST_FIRST(head); \ + (var)!= LIST_END(head); \ + (var) = LIST_NEXT(var, field)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + LIST_FIRST(head) = LIST_END(head); \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for((var) = SIMPLEQ_FIRST(head); \ + (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * tail queue access methods + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_PREV(var, headname, field)) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ +} while (0) + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \ + { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue access methods + */ +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define CIRCLEQ_LAST(head) ((head)->cqh_last) +#define CIRCLEQ_END(head) ((void *)(head)) +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) +#define CIRCLEQ_EMPTY(head) \ + (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for((var) = CIRCLEQ_FIRST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_NEXT(var, field)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for((var) = CIRCLEQ_LAST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_PREV(var, field)) + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = CIRCLEQ_END(head); \ + (head)->cqh_last = CIRCLEQ_END(head); \ +} while (0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = CIRCLEQ_END(head); \ + if ((head)->cqh_last == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = CIRCLEQ_END(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (0) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ + _Q_INVALIDATE((elm)->field.cqe_prev); \ + _Q_INVALIDATE((elm)->field.cqe_next); \ +} while (0) + +#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ + CIRCLEQ_END(head)) \ + (head).cqh_last = (elm2); \ + else \ + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ + CIRCLEQ_END(head)) \ + (head).cqh_first = (elm2); \ + else \ + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ + _Q_INVALIDATE((elm)->field.cqe_prev); \ + _Q_INVALIDATE((elm)->field.cqe_next); \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/compat/strtonum.c b/compat/strtonum.c new file mode 100644 index 0000000..e426388 --- /dev/null +++ b/compat/strtonum.c @@ -0,0 +1,65 @@ +/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */ + +/* + * Copyright (c) 2004 Ted Unangst and Todd Miller + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +#define INVALID 1 +#define TOOSMALL 2 +#define TOOLARGE 3 + +long long +strtonum(const char *numstr, long long minval, long long maxval, + const char **errstrp) +{ + long long ll = 0; + char *ep; + int error = 0; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid", EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; + + ev[0].err = errno; + errno = 0; + if (minval > maxval) + error = INVALID; + else { + ll = strtoll(numstr, &ep, 10); + if (numstr == ep || *ep != '\0') + error = INVALID; + else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) + error = TOOSMALL; + else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + ll = 0; + + return (ll); +} diff --git a/configure b/configure new file mode 100755 index 0000000..7150f1b --- /dev/null +++ b/configure @@ -0,0 +1,78 @@ +#!/bin/sh +# $Id: configure,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ +# +# This configure script was greatly inspired by the script distributed with tmux +# from Nicholas Marriott. The license from the original script is reproduced +# below: +# +# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER +# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +OLDRUNNER_PLATFORM=${OLDRUNNER_PLATFORM:-`uname -s`} + +CONFIG_H=config.h +rm -f $CONFIG_H +echo "/* $OLDRUNNER_PLATFORM */" >$CONFIG_H + +CONFIG_MK=config.mk +rm -f $CONFIG_MK +echo "# $OLDRUNNER_PLATFORM" >$CONFIG_MK + +cat <<EOF >>$CONFIG_H +#undef HAVE_CURSES_H +#undef HAVE_NCURSES_H +#undef HAVE_NCURSES_NCURSES_H +#undef HAVE_NCURSESW_NCURSES_H +#undef HAVE_BZERO +#undef HAVE_FGETLN +#undef HAVE_QUEUE_H +#undef HAVE_STRTONUM +EOF + +case $OLDRUNNER_PLATFORM in +# ------------------------------------------------------------------------------ + OpenBSD|FreeBSD) + cat <<EOF >>$CONFIG_H +#define HAVE_CURSES_H +#define HAVE_BZERO +#define HAVE_FGETLN +#define HAVE_QUEUE_H +#define HAVE_STRTONUM +EOF + cat <<EOF >>$CONFIG_MK +LIBS+= -lcurses +EOF + ;; +# ------------------------------------------------------------------------------ + Linux) + cat <<EOF >>$CONFIG_H +#define HAVE_NCURSES_H +#define HAVE_BZERO +EOF + cat <<EOF >>$CONFIG_MK +CFLAGS+= -std=c99 -D_GNU_SOURCE -D_POSIX_SOURCE +LIBS+= -lncurses +SRCS+= compat/fgetln.c \ + compat/strtonum.c +EOF + ;; +# ------------------------------------------------------------------------------ + *) + echo Unable to configure for $OLDRUNNER_PLATFORM + exit 1 +esac + +echo Configured for $OLDRUNNER_PLATFORM +exit 0 @@ -0,0 +1,117 @@ +/* $Id: coord.c,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "oldrunner.h" + +void +coord_copy (const struct coord *orig, struct coord *dest) +{ + dest->y = orig->y; + dest->x = orig->x; +} + +void +coord_below (const struct coord *orig, struct coord *dest) +{ + dest->y = orig->y + 1; + dest->x = orig->x; +} + +void +coord_above (const struct coord *orig, struct coord *dest) +{ + dest->y = orig->y - 1; + dest->x = orig->x; +} + +enum move +coord_opposite_dir (enum move dir) +{ + switch (dir) + { + case MOV_RIGHT: + return MOV_LEFT; + case MOV_LEFT: + return MOV_RIGHT; + case MOV_UP: + return MOV_DOWN; + case MOV_DOWN: + return MOV_UP; + default: + return MOV_NONE; + } +} + +void +coord_compute (const struct coord *orig, enum move move, struct coord *dest) +{ + coord_copy (orig, dest); + switch (move) + { + case MOV_UP: + dest->y--; + break; + case MOV_DOWN: + case MOV_FALL: + dest->y++; + break; + case MOV_LEFT: + dest->x--; + break; + case MOV_RIGHT: + dest->x++; + break; + default: + dest->y = dest->x = 0; + /* NOTREACHED */ + } +} + +void +coord_set_yx (struct coord *coord, int y, int x) +{ + coord->y = y; + coord->x = x; +} + +unsigned +coord_equal (const struct coord *p1, const struct coord *p2) +{ + return p1->x == p2->x && p1->y == p2->y ? 1 : 0; +} + +void +coord_diff (const struct coord *p1, const struct coord *p2, struct coord *diff) +{ + diff->y = p1->y - p2->y; + diff->x = p1->x - p2->x; +} @@ -0,0 +1,290 @@ +/* $Id: foes.c,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "oldrunner.h" + +#define FOES_DELAY (OLDRUNNER_TIMEOUT * 3) +#define FOES_ESCAPE_DELAY (BRICK_COMEBACK_TIME * .75) + +struct foe { + struct coord pos; + struct timer timer; + enum move current_move; + int state; + SLIST_ENTRY(foe) foesp; +}; + +SLIST_HEAD(, foe) foes; + +void +foes_init (void) +{ + SLIST_INIT (&foes); +} + +void +foes_free (void) +{ + while (!SLIST_EMPTY (&foes)) + { + struct foe *f; + + f = SLIST_FIRST (&foes); + SLIST_REMOVE_HEAD (&foes, foesp); + xfree (f); + } +} + +void +foes_add (const struct coord *pos) +{ + struct foe *f; + + f = xmalloc (sizeof *f); + coord_set_yx (&f->pos, pos->y, pos->x); + f->current_move = MOV_NONE; + f->state = STATE_ALIVE; + SLIST_INSERT_HEAD (&foes, f, foesp); +} + +void +foes_draw (void) +{ + struct foe *f; + + SLIST_FOREACH (f, &foes, foesp) + gfx_show_sprite (SP_FOE, &f->pos); +} + +/* + * Once killed, a foe reappears on top of current level with + * a random horizontal position. + */ +static void +get_random_inipos (struct coord *pos) +{ + coord_set_yx (pos, 0, -1); + while (lvl_obstacle_at (pos)) + pos->x = lvl_random_xpos (); +} + +static void +foe_killed (struct foe *foe) +{ + struct coord inipos; + + get_random_inipos (&inipos); + coord_copy (&inipos, &foe->pos); + foe->current_move = MOV_FALL; + foe->state = STATE_ALIVE; +} + +static void +foe_trapped (struct foe *foe) +{ + foe->state |= STATE_TRAPPED; + timer_start (&foe->timer); +} + +static void +check_trap (struct foe *foe) +{ + if (lvl_got_hole_below (&foe->pos)) + { + struct coord below; + + foe_trapped (foe); + coord_below (&foe->pos, &below); + gfx_move_sprite (SP_FOE, &foe->pos, &below); + coord_copy (&below, &foe->pos); + } +} + +static void +check_hole (struct foe *foe) +{ + if (lvl_nothing_below (&foe->pos)) + foe->current_move = MOV_FALL; +} + +static unsigned +another_foe_at_pos (const struct foe *foe, const struct coord *pos) +{ + struct foe *f; + + SLIST_FOREACH (f, &foes, foesp) + if (f != foe && coord_equal (pos, &f->pos)) + return 1; + + return 0; +} + +unsigned +foes_at_pos (const struct coord *pos) +{ + struct foe *f; + + SLIST_FOREACH (f, &foes, foesp) + if (coord_equal (pos, &f->pos)) + return 1; + + return 0; +} + +static void +compute_move (const struct coord *hero, struct foe *foe) +{ + struct coord dpos; + + if (foe->current_move == MOV_FALL) + coord_compute (&foe->pos, foe->current_move, &foe->pos); + else + { + coord_diff (hero, &foe->pos, &dpos); + if (dpos.y != 0) + { + enum move wanted_dir, prefered_move; + + if (foe->current_move != MOV_LEFT && foe->current_move != MOV_RIGHT) + prefered_move = dpos.x >= 0 ? MOV_RIGHT : MOV_LEFT; + else + prefered_move = foe->current_move; + wanted_dir = dpos.y > 0 ? MOV_DOWN : MOV_UP; + foe->current_move = lvl_shortest_way (&foe->pos, + wanted_dir, + prefered_move); + coord_compute (&foe->pos, foe->current_move, &foe->pos); + } + else if (dpos.x > 0) + { + foe->current_move = MOV_RIGHT; + foe->pos.x++; + } + else if (dpos.x < 0) + { + foe->current_move = MOV_LEFT; + foe->pos.x--; + } + else + foe->current_move = MOV_NONE; + } +} + +static void +try_escape (struct foe *f) +{ + struct coord posorig; + + if (!timer_delay_elapsed (&f->timer, FOES_ESCAPE_DELAY)) + return; + + coord_set_yx (&posorig, f->pos.y, f->pos.x); + coord_set_yx (&f->pos, f->pos.y - 1, f->pos.x); + gfx_move_sprite (SP_FOE, &posorig, &f->pos); + f->state &= ~STATE_TRAPPED; +} + +static void +update_foe_pos (const struct coord *hero_pos, struct foe *f) +{ + struct coord posorig; + + coord_set_yx (&posorig, f->pos.y, f->pos.x); + compute_move (hero_pos, f); + if (!coord_equal (&posorig, &f->pos) + && lvl_valid_move (&posorig, f->current_move, &f->pos, SP_FOE) + && !another_foe_at_pos (f, &f->pos)) + { + gfx_move_sprite (SP_FOE, &posorig, &f->pos); + check_trap (f); + check_hole (f); + if (coord_equal (&f->pos, hero_pos)) + hero_die (); + } + else + { + /* + * The move is not possible, revert to current position + * and force next move to be in opposite direction using + * foe->current_move. + */ + coord_copy (&posorig, &f->pos); + f->current_move = + f->current_move == MOV_FALL ? + MOV_NONE : coord_opposite_dir (f->current_move); + } +} + +void +foes_update_pos (void) +{ + static struct timer foes_timer; + struct timer now; + struct foe *foe; + struct coord hero_pos; + + timer_get_time (&now); + if (timer_diff (&now, &foes_timer) < FOES_DELAY) + return; + + hero_get_pos (&hero_pos); + + SLIST_FOREACH (foe, &foes, foesp) + { + struct coord foe_prevpos; + + coord_set_yx (&foe_prevpos, foe->pos.y, foe->pos.x); + + if (foe->state & STATE_TRAPPED) + try_escape (foe); + else + update_foe_pos (&hero_pos, foe); + } + timer_get_time (&foes_timer); +} + +unsigned +foes_wallup_at (const struct coord *pos) +{ + struct foe *f; + + SLIST_FOREACH (f, &foes, foesp) + { + if (coord_equal (pos, &f->pos)) + { + foe_killed (f); + return 1; + } + } + + return 0; +} @@ -0,0 +1,297 @@ +/* $Id: game.c,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#include "oldrunner.h" + +#ifdef LEVELS_PATH +# define LEVELS LEVELS_PATH "/original.lvl" +#else +# define LEVELS "./levels/original.lvl" +#endif + +#define POINTS_FOR_MONEY 50 +#define LIVES_AT_START 5 + +static struct game_info ginfo; + +static void +game_lost (void) +{ + struct usr_input input; + + gfx_game_over (); + gfx_get_input (&input); + game_end (); +} + +void +game_won (void) +{ + struct usr_input input; + + gfx_game_won (); + gfx_get_input (&input); + game_end (); +} + +void +game_init (int startlvl) +{ + lvl_init (); + if (!game_load (LEVELS)) + EXIT ("Could not load game levels. Aborting..."); + ginfo.lives = LIVES_AT_START; + ginfo.level = startlvl + 1; + gfx_init (); + lvl_load (startlvl); + hero_init (); + game_update (); +} + +/* + * The window will be centered on player either if the user requests it or if + * the level board is too large to fit it the screen. + */ +static void +set_view (void) +{ + struct size lvl; + + lvl.w = lvl_width (); + lvl.h = lvl_height (); + + if (AUTO_CENTER_MODE || lvl.h > VIEWPORT_HEIGHT || lvl.w > VIEWPORT_WIDTH) + { + struct coord player_pos; + + hero_get_pos (&player_pos); + gfx_center_at (&player_pos); + } + else + { + struct coord fixed_pos; + + coord_set_yx (&fixed_pos, VIEWPORT_HEIGHT / 2, lvl.w / 2); + gfx_center_at (&fixed_pos); + } +} + +void +game_update (void) +{ + set_view (); + lvl_objects_update (); + hero_draw (); + if (!(ginfo.state & NO_CHANGE)) + { + gfx_update_info (&ginfo); + ginfo.state = NO_CHANGE; + } + gfx_update (); +} + +void +game_end (void) +{ + gfx_end (); + exit (0); +} + +static unsigned +read_level_row (char *row, unsigned rownum) +{ + char *rowend; + int len; + + if (*row != '[') + return 0; + row++; + + if (!(rowend = strchr (row, ']'))) + return 0; + *rowend = '\0'; + len = rowend - row; + + return lvl_set_row (rownum, len, row); +} + +static unsigned +store_level_attr (const char *attr, char *val) +{ + if (!strcmp (attr, "level")) + return lvl_set_name (val); + else if (!strcmp (attr, "author")) + return lvl_set_author (val); + else if (!strcmp (attr, "size")) + return lvl_set_size (val); + else + return 0; +} + +/* XXX use strsep instead. */ +static unsigned +read_level_attr (char *line) +{ + char *p, *attr, *val; + + attr = p = line; + + while (!isblank ((int)(*p))) + p++; + *p++ = '\0'; + + while (isblank ((int)(*p))) + p++; + val = p; + + return store_level_attr (attr, val); +} + +/* + * XXX improve comment. + * + * A game file contains the description of the levels. + * The following rules apply: + * - empty lines are ignored, as well as those beginning with # + * - the following keywords are used to describe a level: + * - level: name of the level (default: "") + * - author: author of the level (default: "") + * - size: in the form widthxlength (default: 26x16) + * - if keywords are present, they must be placed before the level layout + * - the reading of a level row stops as soon as the line does + * not start with '[', meaning a layout description must not have empty + * lines + */ +unsigned +game_load (const char *path) +{ + FILE *f; + char *buf; + unsigned rownum, newlevel; + + if (!(f = io_fopen (LEVELS))) + return 0; + + newlevel = 1; + rownum = 0; + while ((buf = io_getln (f))) + { + char *p; + +#define CHK_NEW_LVL do { \ + if (newlevel) \ + { \ + lvl_add_new (); \ + newlevel = 0; \ + rownum = 0; \ + } \ + } while (0) + + /* Remove trailing spaces. */ + p = buf; + while (isblank ((int)(*p))) + p++; + + switch (*p) + { + case '[': + CHK_NEW_LVL; + read_level_row (p, rownum); + rownum++; + break; + case '#': + case '\0': + if (rownum) + newlevel = 1; + continue; + default: + if (rownum) + newlevel = 1; + CHK_NEW_LVL; + read_level_attr (p); + break; + } + +#undef CHK_NEW_LVL + } + + io_fclose (f); + + return 1; +} + +void +game_score_inc (void) +{ + ginfo.state |= SCORE_CHANGE; + ginfo.score += POINTS_FOR_MONEY; +} + +int +game_level_num (void) +{ + return ginfo.level; +} + +void +game_level_inc (void) +{ + ginfo.state |= LEVEL_CHANGE; + ginfo.level++; +} + +void +game_level_dec (void) +{ + ginfo.state |= LEVEL_CHANGE; + ginfo.level--; +} + +void +game_lives_inc (void) +{ + ginfo.state |= LIVES_CHANGE; + ginfo.lives++; +} + +void +game_lives_dec (void) +{ + ginfo.state |= LIVES_CHANGE; + if (ginfo.lives == 0) + game_lost (); + ginfo.lives--; +} @@ -0,0 +1,448 @@ +/* $Id: gfx.c,v 1.2 2012/01/31 14:53:07 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> + +#include "oldrunner.h" + +#ifdef HAVE_CURSES_H +# include <curses.h> +#elif defined HAVE_NCURSES_H +# include <ncurses.h> +#elif defined HAVE_NCURSES_NCURSES_H +# include <ncurses/ncurses.h> +#elif defined HAVE_NCURSESW_NCURSES_H +# include <ncursesw/ncurses.h> +#else +# error "Missing curses library header. Aborting..." +#endif + +#define INFOBAR_HEIGHT 2 + +struct window { + WINDOW *p; /* pointer to window */ + struct size siz; + struct coord pos; +}; + +struct scrollwin { + struct window pad; + struct window view; +}; + +static struct scrollwin scr; +static struct size term; + +static chtype sprite[SPRITES]; + +static void +sprites_init (void) +{ + sprite[SP_NONE] = ' '; + sprite[SP_BRICK] = ACS_CKBOARD; + sprite[SP_BRICK_SCRACK] = '~'; + sprite[SP_BRICK_LCRACK] = 'U'; + sprite[SP_BRICK_BROKEN] = sprite[SP_NONE]; + sprite[SP_CIMENT] = ' ' | A_REVERSE; + sprite[SP_FAKE_BRICK] = sprite[SP_BRICK]; + sprite[SP_LADDER] = 'H'; + sprite[SP_ROPE] = ACS_HLINE; + sprite[SP_ESCAPE_LADDER] = ACS_VLINE; + sprite[SP_MONEY] = ACS_DIAMOND; + sprite[SP_HERO] = '@'; + sprite[SP_FOE] = '@' | A_REVERSE | A_BLINK; + sprite[SP_INVALID] = '?'; +} + +static void +screen_init_size (void) +{ + scr.view.siz.w = VIEWPORT_WIDTH; + scr.view.siz.h = VIEWPORT_HEIGHT; + + getmaxyx (stdscr, term.h, term.w); /* Size of the terminal. */ + coord_set_yx (&scr.view.pos, + term.h > scr.view.siz.h ? (term.h - scr.view.siz.h) / 2 : 0, + term.w > scr.view.siz.w ? (term.w - scr.view.siz.w) / 2 : 0); + scr.pad.siz.w = LEVEL_MAX_WIDTH; + scr.pad.siz.h = LEVEL_MAX_HEIGHT; + coord_copy (&scr.view.pos, &scr.pad.pos); +} + +static void +screen_init (void) +{ + screen_init_size (); + scr.pad.p = newpad (scr.pad.siz.h, scr.pad.siz.w); + scr.view.p = newwin (scr.view.siz.h, scr.view.siz.w, + scr.view.pos.y, scr.view.pos.x); + keypad (scr.view.p, TRUE); /* Enable function and arrow keys. */ + nodelay (scr.view.p, TRUE); + box (scr.view.p, 0, 0); + wnoutrefresh (scr.view.p); +} + +static void +screen_update (void) +{ + pnoutrefresh (scr.pad.p, scr.pad.pos.y, scr.pad.pos.x, + scr.view.pos.y + (scr.view.siz.h - lvl_height()) / 2, + scr.view.pos.x + (scr.view.siz.w - lvl_width()) / 2, + scr.view.pos.y + scr.view.siz.h - INFOBAR_HEIGHT, + scr.view.pos.x + scr.view.siz.w - 2); +} + +static void +newpopup (struct window *pop) +{ + const int BORDERWIDTH = 2; + + pop->siz.w = scr.view.siz.w - 2 * BORDERWIDTH; + pop->siz.h = scr.view.siz.h - 2 * BORDERWIDTH; + pop->pos.y = scr.view.pos.y + BORDERWIDTH; + pop->pos.x = scr.view.pos.x + BORDERWIDTH; + + pop->p = newwin (pop->siz.h, pop->siz.w, pop->pos.y, pop->pos.x); + keypad (pop->p, TRUE); +} + +static void +delpopup (struct window *pop) +{ + wclear (pop->p); + wrefresh (pop->p); + delwin (pop->p); +} + +static void +showpopup (struct window *pop) +{ + box (pop->p, 0, 0); + wrefresh (pop->p); +} + +void +gfx_init (void) +{ + /* Curses initialization. */ + initscr (); /* start the curses mode */ + cbreak (); /* control chars generate a signal */ + noecho (); /* controls echoing of typed chars */ + curs_set (0); /* make cursor invisible */ + sprites_init (); + + /* Game window initialization. */ + screen_init (); +} + +void +gfx_end (void) +{ + wclear (scr.view.p); + wrefresh (scr.view.p); + delwin (scr.pad.p); + delwin (scr.view.p); + endwin (); +} + +void +gfx_alert (void) +{ + flash (); + napms (200); + flash (); +} + +void +gfx_center_at (struct coord *pos) +{ + coord_set_yx (&scr.pad.pos, + pos->y - VIEWPORT_HEIGHT / 2, pos->x - VIEWPORT_WIDTH / 2); +} + +void +gfx_update (void) +{ + screen_update (); + doupdate (); +} + +void +gfx_get_input (struct usr_input *input) +{ + int key; + + key = wgetch (scr.view.p); + input->key = key == ERR ? -1 : key; +} + +void +gfx_show_sprite (enum sprite sp, const struct coord *pos) +{ + gfx_move_sprite (sp, 0, pos); +} + +/* + * Show the given character at the current position. + * The optional previous position is also given so that graphics routines can + * properly clean it up if necessary. + * + * note: + * If the viewport is larger than the level size, a shift must be applied in + * order to center the level on screen. + */ +void +gfx_move_sprite (enum sprite sp, const struct coord *prev, + const struct coord *current) +{ + mvwaddch (scr.pad.p, current->y, current->x, sprite[sp]); + if (prev) + { + sp = lvl_decor_at_pos (prev); + mvwaddch (scr.pad.p, prev->y, prev->x, sprite[sp]); + } + + screen_update (); +} + +/* + * Display information related to current game (score, number of lives and + * current level). + */ +void +gfx_update_info (const struct game_info *info) +{ + const int HIGHLIGHT = WA_REVERSE | WA_BOLD; + char score[BUFSIZ], lives[BUFSIZ], level[BUFSIZ]; + int score_len, lives_len, level_len, yoff, xoff; + + score_len = snprintf (score, sizeof score, "[SCORE: %010d]", info->score); + lives_len = snprintf (lives, sizeof lives, "[LIVES: %03d]", info->lives); + level_len = snprintf (level, sizeof level, "[LEVEL: %03d]", info->level); + + yoff = scr.view.siz.h - INFOBAR_HEIGHT + 1; + xoff = scr.view.siz.w - (score_len + lives_len + level_len); + xoff >>= 2; + + if (info->state & SCORE_CHANGE) + wattron (scr.view.p, HIGHLIGHT); + mvwprintw (scr.view.p, yoff, xoff, score); + if (info->state & SCORE_CHANGE) + wattroff (scr.view.p, HIGHLIGHT); + + if (info->state & LIVES_CHANGE) + wattron (scr.view.p, HIGHLIGHT); + mvwprintw (scr.view.p, yoff, score_len + 2 * xoff, lives); + if (info->state & LIVES_CHANGE) + wattroff (scr.view.p, HIGHLIGHT); + + if (info->state & LEVEL_CHANGE) + wattron (scr.view.p, HIGHLIGHT); + mvwprintw (scr.view.p, yoff, score_len + lives_len + 3 * xoff, level); + if (info->state & LEVEL_CHANGE) + wattroff (scr.view.p, HIGHLIGHT); + + wnoutrefresh (scr.view.p); +} + +void +gfx_popup (const char *title, const char *msg) +{ + struct window pop; + char *any_key = "Press any key..."; + + newpopup (&pop); + + mvwhline (pop.p, 2, 1, ACS_HLINE, pop.siz.w - 2); + mvwprintw (pop.p, 1, (pop.siz.w - strlen (title)) / 2, "%s", title); + + mvwprintw (pop.p, 5, 1, "%s", msg); + mvwprintw (pop.p, pop.siz.h - 2, pop.siz.w - (strlen (any_key) + 1), "%s", + any_key); + + showpopup (&pop); + (void)wgetch (pop.p); + delpopup (&pop); +} + +void +gfx_game_over (void) +{ + const char *rip = + " +-+ \n" + " +-+-+-+ \n" + " +-+-+-+ \n" + " | | \n" + " +------+-+------+ \n" + " | | \n" + " | R I P | \n" + " ~~~~~~~~~~~| |~~~~~~~~~~ \n" + " +---------------+ \n"; + + gfx_popup ("G A M E O V E R", rip); +} + +/* + * The ending screen was taken from the ncurses original sources + * (firework.c file). + * The original copyright is reproduced below. + */ +/**************************************************************************** + * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ +static void +fw_show (struct window *win) +{ + const char *title = "C O N G R A T U L A T I O N S"; + const int titlelen = 29; + + mvwhline (win->p, 2, 1, ACS_HLINE, win->siz.w - 2); + mvwprintw (win->p, 1, (win->siz.w - titlelen) / 2, "%s", title); + showpopup (win); + napms (120); +} + +static void +fw_explode (struct window *win, int row, int col) +{ + werase (win->p); + mvwprintw (win->p, row, col, "-"); + fw_show (win); + + mvwprintw(win->p, row - 1, col - 1, " - "); + mvwprintw(win->p, row + 0, col - 1, "-+-"); + mvwprintw(win->p, row + 1, col - 1, " - "); + fw_show (win); + + mvwprintw(win->p, row - 2, col - 2, " --- "); + mvwprintw(win->p, row - 1, col - 2, "-+++-"); + mvwprintw(win->p, row + 0, col - 2, "-+#+-"); + mvwprintw(win->p, row + 1, col - 2, "-+++-"); + mvwprintw(win->p, row + 2, col - 2, " --- "); + fw_show (win); + + mvwprintw(win->p, row - 2, col - 2, " +++ "); + mvwprintw(win->p, row - 1, col - 2, "++#++"); + mvwprintw(win->p, row + 0, col - 2, "+# #+"); + mvwprintw(win->p, row + 1, col - 2, "++#++"); + mvwprintw(win->p, row + 2, col - 2, " +++ "); + fw_show (win); + + mvwprintw(win->p, row - 2, col - 2, " # "); + mvwprintw(win->p, row - 1, col - 2, "## ##"); + mvwprintw(win->p, row + 0, col - 2, "# #"); + mvwprintw(win->p, row + 1, col - 2, "## ##"); + mvwprintw(win->p, row + 2, col - 2, " # "); + fw_show (win); + + mvwprintw(win->p, row - 2, col - 2, " # # "); + mvwprintw(win->p, row - 1, col - 2, "# #"); + mvwprintw(win->p, row + 0, col - 2, " "); + mvwprintw(win->p, row + 1, col - 2, "# #"); + mvwprintw(win->p, row + 2, col - 2, " # # "); + fw_show (win); +} + +/* XXX quit end screen properly (free popup window) */ +static void +fireworks (void) +{ + struct window pop; + int start, end, row, diff, flag, direction; + + newpopup (&pop); + showpopup (&pop); + flag = 0; + for (;;) + { + do + { + start = rand() % (pop.siz.w - 3); + end = rand() % (pop.siz.w - 3); + start = (start < 2) ? 2 : start; + end = (end < 2) ? 2 : end; + direction = (start > end) ? -1 : 1; + diff = abs (start - end); + } + while (diff < 2 || diff >= pop.siz.h - 2); + + for (row = 0; row < diff; row++) + { + mvwprintw (pop.p, pop.siz.h - row, start + (row * direction), + (direction < 0) ? "\\" : "/"); + if (flag++) + { + fw_show (&pop); + werase (pop.p); + flag = 0; + } + } + if (flag++) + { + fw_show (&pop); + flag = 0; + } + fw_explode (&pop, pop.siz.h - row, start + (diff * direction)); + werase (pop.p); + fw_show (&pop); + } +} + +void +gfx_game_won (void) +{ + fireworks (); +} @@ -0,0 +1,188 @@ +/* $Id: hero.c,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "oldrunner.h" + +struct hero { + struct coord pos, initpos; + int state; +}; + +static struct hero hero; + +void +hero_init (void) +{ + hero.state = STATE_ALIVE; + hero_draw (); + usr_reset_input (); +} + +void +hero_draw (void) +{ + gfx_show_sprite (SP_HERO, &hero.pos); +} + +void +hero_set_pos (const struct coord *pos) +{ + coord_set_yx (&hero.pos, pos->y, pos->x); + if (hero.pos.y < 0) + lvl_won (); +} + +void +hero_set_initpos (const struct coord *pos) +{ + coord_set_yx (&hero.initpos, pos->y, pos->x); +} + +void +hero_get_pos (struct coord *pos) +{ + coord_set_yx (pos, hero.pos.y, hero.pos.x); +} + +void +hero_get_initpos (struct coord *pos) +{ + coord_set_yx (pos, hero.initpos.y, hero.initpos.x); +} + +unsigned +hero_at_pos (const struct coord *pos) +{ + if (coord_equal (&hero.pos, pos)) + return 1; + return 0; +} + +void +check_collisions (const struct coord *hero_pos) +{ + if (lvl_got_hole_below (hero_pos)) + { + struct coord below; + + hero_trapped (); + coord_below (hero_pos, &below); + gfx_move_sprite (SP_HERO, hero_pos, &below); + hero_set_pos (&below); + } + else + { + if (foes_at_pos (hero_pos)) + hero_die (); + money_check_at (hero_pos); + if (money_all_collected ()) + lvl_draw_escape_ladder (); + } +} + +void +hero_move (enum move move) +{ + struct coord orig, dest; + + /* First check if the move is valid with regards to current player state. */ + if (hero.state & STATE_DIGGING) + return; + + if ((hero.state & STATE_FALLING) && (move != MOV_FALL)) + move = MOV_FALL; + + /* Then check if the move is valid with regards to the level layout. */ + hero_get_pos (&orig); + if (!lvl_valid_move (&orig, move, &dest, SP_HERO)) + { + if (hero.state & STATE_FALLING) + hero.state &= ~STATE_FALLING; + return; + } + else + hero_set_pos (&dest); + + if (move == MOV_FALL || lvl_nothing_below (&hero.pos)) + hero.state |= STATE_FALLING; + + gfx_move_sprite (SP_HERO, &orig, &hero.pos); + check_collisions (&hero.pos); +} + +void +hero_dig (enum move dir) +{ + struct coord heropos, digpos; + + hero_get_pos (&heropos); + coord_set_yx (&digpos, + heropos.y + 1, heropos.x + (dir == MOV_RIGHT ? 1 : -1)); + if (lvl_valid_dig (&digpos)) + { + hero.state |= STATE_DIGGING; + bricks_break (&digpos); + } +} + +void +hero_dig_done (void) +{ + hero.state &= ~STATE_DIGGING; +} + +void +hero_trapped (void) +{ + hero.state |= STATE_TRAPPED | STATE_FALLING; + usr_reset_input (); +} + +void +hero_die (void) +{ + gfx_alert (); + game_lives_dec (); + lvl_lost (); +} + +unsigned +hero_wallup_at (const struct coord *pos) +{ + if (coord_equal (pos, &hero.pos)) + { + hero_die (); + return 1; + } + + return 0; +} @@ -0,0 +1,86 @@ +/* $Id: io.c,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "oldrunner.h" + +FILE * +io_fopen (const char *path) +{ + FILE *f; + + if (!(f = fopen (path, "r"))) + { + ERROR_MSG ("Could not open game file \"%s\": %s", + path, strerror (errno)); + return 0; + } + + return f; +} + +static char *line; + +void +io_fclose (FILE *f) +{ + (void)fclose (f); + if (line) + xfree (line); + line = 0; +} + +char * +io_getln (FILE *f) +{ + size_t len; + char *buf; + + line = 0; + if (!(buf = fgetln (f, &len))) + return 0; + if (buf[len - 1] == '\n') + buf[len - 1] = '\0'; + else + { + /* EOF without EOL, copy and add the NUL */ + line = xrealloc (line, 1, len + 1); + memcpy (line, buf, len); + line[len] = '\0'; + buf = line; + } + + return buf; +} diff --git a/levels/original.lvl b/levels/original.lvl new file mode 100644 index 0000000..4a57f75 --- /dev/null +++ b/levels/original.lvl @@ -0,0 +1,3155 @@ +#----------------------------------------------------------------------------- +level "Level 0 (original)" +author "Broderbund" +size 0x0 + +#----------------------------------------------------------------------------- +level "Level 1 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ $ | ] +[######H####### | ] +[ H----------| $ ] +[ H ##H ######H##] +[ H ##H H ] +[ &H ##H $&H ] +[##H#### ########H######] +[ H H ] +[ H & H ] +[########H##########H ] +[ H H ] +[ $ H----------H $ ] +[ H##### ######H] +[ H @ $ H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 2 (original)" +author "Broderbund" +size 26x16 +[ $ H] +[HXX#XXH $ H] +[H H H########H $ H] +[H $ & H H H###VH] +[H#X#X#H H H |] +[H H----H----- &H |] +[H H H H###XXXXXH] +[H H H $ H H] +[H & H $ H####H H] +[X###X##X##XH H##H##] +[X###X H H H ] +[X$ X H ------H H $] +[########H###XXX H ####] +[ H H ] +[ H @ H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 3 (original)" +author "Broderbund" +size 26x16 +[ |] +[--------- $ |] +[H$ H#########H |] +[####H H HXXXXXXX] +[ H & H $ H ] +[ H#####H#####H## ] +[ $ H H H -- ] +[###H# H & H -- ] +[ H H#####H## --$] +[ H----H H & #] +[ H H#########H ] +[ H H#########H ] +[##H######### $ #####H#] +[##H######### H###H #####H#] +[ H @ H###H H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 4 (original)" +author "Broderbund" +size 26x16 +[| ] +[|---------- ] +[H H # $ # H ] +[H$ HHH $ ##### $ HHH $] +[ HH H HH HH H HH] +[ H HHHHH H H HHHHH H] +[ H $&$ H H H $&$ H] +[H H#####H HHH H#####H ] +[H HHHHH HH H HH HHHHH ] +[H H HHHHH H ] +[H $ H $&$ H $ ] +[H#####H H#####H H######] +[H H HHHHH H ] +[H H H ] +[H H $ @ H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 5 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | $ & ] +[### | ###H######] +[ # | ## H ] +[ ## | ## H ] +[$& ### | $### H $ ] +[##H#### | ####H##H######] +[ H ## | ## H ] +[ H$& ##H## H $ ] +[H###H H #H#H### ] +[H H H ] +[H H $ & H ] +[H H#######H#####H####H##] +[H H H ] +[H H @ H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 6 (original)" +author "Broderbund" +size 26x16 +[################|#########] +[# $ |# & $ #] +[#V##H####H $ |#######H#] +[#V##H############# ### H#] +[# H $ & #### ### H#] +[#H########H####### ### H#] +[#H ######H####$$# ###$ H#] +[#H ######H#############H#] +[#H # $H $ & $ #H#] +[#H ###H######H#######H#H#] +[#H $###H H#######H#H#] +[#H#V# H @ H ## H#H#] +[#H#V#H#####H#######$$ H#H#] +[#H#V#H#####H#####$######H#] +[#H& H##$##H $ & H#] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 7 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | --------] +[ | & H H] +[####H# #H### &H $ H] +[ H H ###H#######] +[ & H $ H H ] +[####H### H H ] +[ H H H ] +[ $ H $ H H ] +[#H###########H H #### H] +[ H H $ H #### H] +[ H $ H----H # $# H] +[######H H #####H] +[ H H H] +[ H @ $ H & H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 8 (original)" +author "Broderbund" +size 26x16 +[ | | ] +[ | | ] +[ $ H#| |#H & ] +[H#####H-H#| |#H-H#####H] +[H# #H #| |# H# #H] +[H# #H #| |# H# #H] +[H# $ #H #| |# H# $ #H] +[H#####H #| |# H#####H] +[H# #H #| |# H# #H] +[H# #H--#H####H#--H# #H] +[H# # H#H H#H # #H] +[H#&$ # H#H $&H#H # $&#H] +[H##V## HXXXXXXX#H ##V##H] +[H V H H V H] +[H VH& @ HV H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 9 (original)" +author "Broderbund" +size 26x16 +[| ] +[|-------------------------] +[H# & # # #] +[H ##### ##### ] +[H # ### #$### ] +[H ##### & & & ##### ] +[H ### #V############### # ] +[H #####V### $## $######H# ] +[H #####V###############H# ] +[H #####V###############H# ] +[H #####V#### #######H# ] +[H #####V#### #######H# ] +[H #####V#### $H######H# ] +[H ####H------H ] +[H XXXX ] +[H @ XXXX & ] + +#----------------------------------------------------------------------------- +level "Level 10 (original)" +author "Broderbund" +size 26x16 +[ $ | ] +[ H###### $ | ] +[ $ H ###### | ] +[##########H $ | ] +[ H######|####H## ] +[& H | H ] +[##########H | & H $] +[##########H#######XX H###] +[##########H H ] +[##########H $ ---H ] +[## ##H ## H ] +[## $$ ##H $ H ] +[###########H######H H ] +[ H #######H] +[ $ @ H H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 11 (original)" +author "Broderbund" +size 26x16 +[ H ] +[ &$ H $& ] +[H##&$ H $&##H] +[H ## H####|H#####H ## H] +[H HH$ H H] +[H $HH H H] +[H HH$ H] +[H $HH H] +[H HH$ H] +[H $HH H] +[H HH$ H] +[H $HH H] +[H HH$ H] +[H $HH H] +[H @ HH$ H] +[H H##############H H] + +#----------------------------------------------------------------------------- +level "Level 12 (original)" +author "Broderbund" +size 26x16 +[ $ $ H ] +[H###############H H ] +[H $ H-----H $] +[#########H####### H###] +[########HH H ] +[#######HH------H H ] +[#$ $##HH & H $ & H $] +[#####HH H####XX####H###] +[ H H H ] +[ H H H ] +[ &H $ H----------H $] +[H##########H $ $ H###] +[H H ######## H ] +[H H H ] +[H $ H @ $ H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 13 (original)" +author "Broderbund" +size 26x16 +[ & & ] +[VHVHVHVHVHVHVHVHVHVHVHVHV|] +[VHVHVHVHVHVHVHVHVHVHVHVHV|] +[#H H#H$H#H H#H$H#H H#H$H#|] +[#HVH#HVH#HVH#HVH#HVH#HVH#|] +[#HVH#HVH#HVH#HVH#HVH#HVH#|] +[#HVH#HVH#HVH#HVH#HVH#HVH#|] +[#H$H#H H#H$H#H H#H$H#H H#|] +[#HVH#HVH#HVH#HVH#HVH#HVH#|] +[#HVH#HVH#HVH#HVH#HVH#HVH#|] +[$H H H H H H H H H H H H#|] +[H########################|] +[H $ & $ $ & |] +[HXXXXXXXXXXXXXXXXXXXXXXXX|] +[H$ @ $|] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 14 (original)" +author "Broderbund" +size 26x16 +[ H & - &-H H- $] +[ -H -H- - - H- H -H] +[- H - H - - H - H H] +[$ H - H - - H -$H -H] +[ H- -H -- H$ -H H] +[H- - H- -- - H------ ] +[H - -H -$ - H - H ] +[H- - H$--H - H -H ] +[H - - H-- H - H - H ] +[H- $ -&H- H - -H- - H ] +[H -H - H - - H ] +[H- H - H - - - H ] +[H -H - - H$- - - H ] +[H- H - H- - $- - H$] +[H -H - -H - - - -H-] +[ H $ $@ H ] + +#----------------------------------------------------------------------------- +level "Level 15 (original)" +author "Broderbund" +size 26x16 +[| |] +[| $ & $ $ & $ |] +[|||########H H#######|||] +[ H H ] +[ H#############H ] +[$ & $H $ $ H$ & $] +[######H $ $#####$ $ H#####] +[ H #### #### H ] +[ $ H $ H $ ] +[ H####################H ] +[ H @ H ] +[ H $ $H#######H$ $H ] +[#########H H########] +[ H H ] +[ $ H H $ ] +[#X#X#X#X#X#X#X#X#X#X#X#X#X] + +#----------------------------------------------------------------------------- +level "Level 16 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ @ | ] +[ V####HH#####HHHHH |] +[ H # H | ] +[ $ H H# H | ] +[ #$ HH# H | ] +[ ###$ H# H | ] +[ #####$ H# H | ] +[######## H# H | ] +[ $##### H# H | ] +[ ### H# H | ] +[ # H# H | ] +[ & H# H & |] +[ H#############V######## |] +[ ############## H#|] +[############### $$$$$$H##] + +#----------------------------------------------------------------------------- +level "Level 17 (original)" +author "Broderbund" +size 26x16 +[| |] +[| |] +[| & |] +[H###V####################H] +[H###V####################H] +[H $ ##-------## H] +[H $#H & $## & H] +[H ### ##H ####### ####H] +[H #$# ##H ## #$##H] +[H @ ##H ## ####H] +[H ### #######HH## #$##H] +[H ### #######HH## ####H] +[H ### ## H ## H] +[H ### ## $H ## $ H] +[##########H########H######] +[####### $H##### $ H######] + +#----------------------------------------------------------------------------- +level "Level 18 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | $ $ $] +[HV#H H###H H##H# #H] +[H ###### H####H H $ H] +[H$ & H H #### H] +[HV#### ##H# H] +[H X#### ## H# H] +[H X##### ## H#H H] +[H X########### $ H ##] +[H X########### ## H ] +[H X ### ### H &$] +[H X $ ## $ ## & H ##] +[H XH###########H####H ##] +[H H H H ##] +[H H @ H ##] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 19 (original)" +author "Broderbund" +size 26x16 +[ H##H ] +[ &$H##H$& ] +[ H######H ] +[ $H######H$ ] +[ H##########H ] +[ &$H##########H$& ] +[ H##############H ] +[ $H $$$$$$$$ H$ ] +[ H##################H ] +[ $H##################H$ ] +[ H######################H ] +[ H######################H ] +[ H H ] +[ H H ] +[ H @ H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 20 (original)" +author "Broderbund" +size 26x16 +[ &$ ] +[ #######H & $ ] +[ & $ H#H#####H] +[ $#####H H H H] +[##V### H------H H$ H] +[ H H #######] +[ $ H H ] +[##H H H--------] +[$ H & H $ H $] +[######## #######H ####] +[ $ $ H ] +[####H###V###H $ H $ ] +[ H #############H] +[ H H] +[ H $ @ $ H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 21 (original)" +author "Broderbund" +size 26x16 +[XXXXXXXXXXXXXXXXXXXXXXXXX|] +[H---------------------H|||] +[H H ## & $ H|$ ] +[H H ####################H] +[H H ### H] +[H H # #################] +[H H H# $ # $ # $ # $ ] +[H H H##H################] +[H H--H H##### #### ] +[H H H H # $# & ] +[H H H H--H ####H-######] +[H H H H H H ######] +[H H H H H--H H ######] +[H H H H H H H## $$$ ] +[H H@ H H &H H H##H####] +[##################H$$H####] + +#----------------------------------------------------------------------------- +level "Level 22 (original)" +author "Broderbund" +size 26x16 +[ $ $ ] +[$$###############H ] +[## $ $ H ] +[ H########H $ $ ] +[ H H####### ] +[ $&$ H ] +[ H#####H------ $ ] +[ H H H########H] +[ $ H H H H] +[###H & H & $ H $ H] +[ H###H######H H#####] +[ H-------- $ H ] +[ $H$ H#####H $ ] +[######H H H#####] +[ H H ] +[ H $ @ H $ ] + +#----------------------------------------------------------------------------- +level "Level 23 (original)" +author "Broderbund" +size 26x16 +[ XXXXXXXX | ] +[ X X | XX ] +[ X $$ & #H | XX ] +[X##H########XXH & |$XX ] +[###H###########H##XX#HXXXX] +[##HHH#-------#HHH#---H---H] +[##H H# $ #H H# $ $ H] +[##H H# @ #H H# H] +[##H$H####H####H$H#X XH] +[#########H###############H] +[ ##HHH## $ $ $ H] +[------#HH HH-------------H] +[ $ #H H & H] +[ H H ########## H] +[XXX H H ### $## $ ##H] +[X#####XH$ $H ############] + +#----------------------------------------------------------------------------- +level "Level 24 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ || ] +[ || ] +[ || ] +[ || ] +[ | ] +[ H##H ] +[ H##H$ ] +[ H#######H & ] +[#H & H# $ $ #H #H#H ] +[ ###H############H###H ] +[ ## $ #### $ H$ ##H ] +[ ####H $ ###H H##H #H ] +[ #$#H###H $ H H$#H$#H ] +[ & ##################H @] +[XXXXXXXXXXXXXXXXXXXXXXXXXX] + +#----------------------------------------------------------------------------- +level "Level 25 (original)" +author "Broderbund" +size 26x16 +[ X X X |] +[ X X X $ |] +[ XV####X X#### ###|] +[## ###H& $ $|] +[##########H H######## #H] +[ @ H ##H $ #H] +[H#########H $#H #####H #H] +[--------##H ##H # H #H] +[ # # $##H HH # ###H #H] +[ # # #HH####H##$###H #H] +[ # $# #H# # ###H H] +[ #### #H# #### # H#HH] +[H## ##HHH# #$## #######H ] +[H XX#HH## # ##$ H#] +[H X H##V####V#######H#] +[H### H & H ] + +#----------------------------------------------------------------------------- +level "Level 26 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ & | ] +[H##########H & $ $ | ] +[H H#####H ##H###] +[H $ $ H XH H ] +[H # ### # H $$ XH & H ] +[H # ### # H XX X########X] +[H # ### # H XX X$] +[H # ### # H X------ $ XH] +[H #$ ### # H X$ ###HXH] +[H ##### # H XX H H] +[H ######## H XX $ H##] +[H H XX #### H ] +[HXXXXXXXX#XXXXX H ] +[H @ H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 27 (original)" +author "Broderbund" +size 26x16 +[| |] +[| @ & |] +[| X#H#X----------X#H#X |] +[| X$H X $ $ X H X |] +[|X## H ##X X## H$##X|] +[|X$ H $X $ $X $ H #$X|] +[X####H ##X X#####H # #|] +[H H X $X$ H # $] +[H H#####XH#X## $H ## #] +[H$ & H & H ##H ] +[H####H X##H###X H #H] +[HX $ H # H $ # H &XH] +[HX## H ### H ### H ##XH] +[H $# H X H $X H X$ H] +[H ### H ### H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 28 (original)" +author "Broderbund" +size 26x16 +[ | ] +[----------- | ] +[ $ $ XH | $ ] +[#########XXXXXXH $HXH ] +[#X#X#X#XXXX XXXXXXXH ] +[ X $ XH &$ ] +[--------H X#####H XX###H] +[ H X H& ###H] +[ H X ########H ###H] +[ $ $ H X # #H ###H] +[###& # H X # $ #H #$#H] +[####### H X ########H # #H] +[ H # $ #H #H] +[############# H##H ######H] +[ @ H $H H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 29 (original)" +author "Broderbund" +size 26x16 +[ & -- - & ] +[#### H - ##H ] +[#### H ## - & -##H ] +[#$$# H ##- ####### -H ] +[#### H ####### H H###] +[ H--- ####### H #$#] +[ - H ####### H ###] +[ #### H ##$$$## H ] +[ - #### H ####### H ] +[###- #$$# H- - -H ] +[#$# #### H - - H #### ] +[### H @ H #### ] +[ H ### H #$$# ] +[ ## H #$# H #### ] +[ ## H #V# H ] +[ H H ] + +#----------------------------------------------------------------------------- +level "Level 30 (original)" +author "Broderbund" +size 26x16 +[X |] +[X $$$$& & & @ |] +[X#########V##############H] +[ H] +[ X $ $ $ $X H] +[ X#######V######V####X H] +[ H] +[ X $ $ $ X H] +[ X###V######V####X H] +[ H] +[ X $ $ $X H] +[ XX############X H] +[ H] +[ H] +[$$$$ & & HX H] +[#########XXXXXX######XXX H] + +#----------------------------------------------------------------------------- +level "Level 31 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | ] +[$ || $] +[H H----------|---------H H] +[#HH & $ HH#] +[##H H------ ---------H H##] +[###HH $ HH###] +[###VH H------ -----H&HV###] +[###V#HH $ HH#V###] +[###V##H H--- ----H H##V###] +[###V###HH $ HH###V###] +[###V####H H-- -H H####V###] +[###V#####HH HH#####V###] +[###V######H H######V###] +[###V#######H@$H#######V###] +[###& H##H ###] + +#----------------------------------------------------------------------------- +level "Level 32 (original)" +author "Broderbund" +size 26x16 +[ ] +[##|#### ----- & ] +[ | -- & XXXXXH] +[ H# #####H######-- # H] +[H### #$---H-----# ####H#] +[H #### ###H# #$ H ] +[H #----H----H# #- H ] +[H@# #H$#$H$#H$H# # H$] +[H## ############ ##H###] +[H $# $ # H ] +[H ## ###H # H ] +[H $# # H # H#####] +[H # # $ H #$ H ] +[H$# # H######H ##$H ] +[H# $ # H# $ H #H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 33 (original)" +author "Broderbund" +size 26x16 +[#####|################ ###] +[ |# ------ ] +[|##| |# #$ #H# & ] +[| ##### #####H#####$ #H###] +[#| $---###H########H# #] +[####### # #H### ####H# #] +[ & #H### ## #H#$ ] +[H#######H#H$#H### ## #H###] +[H H####H###$ # #H## ] +[H H###### #H##$] +[H # H H ] +[H###H####HX#X#X#X#X#X#H#X#] +[H###H####H##### #####H#X#] +[H H H###### ####H ] +[H########H#######$ ######H] +[H@ H $###### & H] + +#----------------------------------------------------------------------------- +level "Level 34 (original)" +author "Broderbund" +size 26x16 +[ -------$$######$$------- ] +[H $###HHHH###$ H] +[H $##HHH&&HHH##$ H] +[H ##HH HH## H] +[H $#HH HH#$ H] +[H ##H$ $H## H] +[H #HH$ $HH# H] +[H #H$$ $$H# H] +[H #HH$ $HH# H] +[H ##H$ $H## H] +[H #HH$ $HH# H] +[H #VHH$$ $$HHV# H] +[H V#HHH$$HHH#V H] +[H ###HHHH### H] +[H@ & ###### & H] +[########H H########] + +#----------------------------------------------------------------------------- +level "Level 35 (original)" +author "Broderbund" +size 26x16 +[| ## |] +[| XX |] +[| $ $ ## $ $ |] +[#X#X#X#X#X#HXXH#X#X#X#X#X#] +[ $ $ H##H $ $ ] +[H#X#X#X#X#X#X#X#X#X#X#X#XH] +[H $ $ ## $ $ H] +[#X#X#X#X#X#HXXH#X#X#X#X#X#] +[ $&&$ H##H $&&$ ] +[H#X#X#X#X#X#XX#X#X#X#X#X#H] +[H $ $ ## $ $ H] +[#X#X#X#X#X#HXXH#X#X#X#X#X#] +[ $ $ H##H $ $ ] +[H#X#X#X#X#X#XX#X#X#X#X#X#H] +[H @ H] +[#X#X#X#X#X#X#X#X#X#X#X#X#X] + +#----------------------------------------------------------------------------- +level "Level 36 (original)" +author "Broderbund" +size 26x16 +[ $ $ $ &$ ] +[H######H### #####H## ####H] +[H H H H] +[ H H - H H ] +[H H - - H H] +[ H H- - H ------H ] +[H------H - H H] +[ & H- -H H ] +[###### H - - H &$ $H] +[## ### H - - H -###XX] +[ $ $ H - H -###XX] +[##V### H - - H -###XX] +[##V# # H - - H -##$$X] +[ $ $ H- -H -XXXXX] +[###### H $ @ H$ XXXXX] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 37 (original)" +author "Broderbund" +size 26x16 +[| ] +[| & ] +[|#########XXXXXX#XXXX#XXXH] +[$ H H] +[## X $ $---$ H] +[####HH#HH######## # # H] +[ #HH HH# XX#### & H] +[ #HH$HH# X #### ###H###H] +[ ####### X$### H H] +[ H H] +[ @ #H#####HXXXH] +[##H#######H### H $$ H H] +[ H H H XX ##H] +[ H##$# H ### XX#### H] +[ H#### &H $ XX H] +[#################XX####XXX] + +#----------------------------------------------------------------------------- +level "Level 38 (original)" +author "Broderbund" +size 26x16 +[| |] +[| |] +[#####H####H& &H####H######] +[ - H HXHXH H - ] +[H #### H $ ##### H] +[H #### #HHHHHHH# ##### H] +[H ##$# #HXXXXXH# #$### H] +[H #### #HHHHHHH# ##### H] +[H ------- H] +[H & H X H & H] +[HXXXXH $XXX$ HXXXXXH] +[H H XXXXX H H] +[H####H XXXXXXX H#####H] +[H H $XXXXXXXXX$ H H] +[HXXXXH XXXXXXXXXXX HXXXXXH] +[$ HXXXXXXXXXXXXXH @ $] + +#----------------------------------------------------------------------------- +level "Level 39 (original)" +author "Broderbund" +size 26x16 +[## | ## ## ## | ##] +[### |#### &#### &####| ###] +[H ##H# ##H# #H## #H## H] +[H #H--H #H $H# H--H# H] +[H&####$H####HH####H$####@H] +[H## ##H# #H## #H## ##H] +[H# #H$ H# $H# #H] +[H## ####HH####HH#### ##H] +[H ##H# ##H# #H## #H## H] +[H #H #H $H# H# H] +[H ####HH####HH####HH#### H] +[H## ##H# #H## #H## ##H] +[H# #H H# H# #H] +[H## ####HH####HH#### ##H] +[H $ HH $ HH $ H] +[H########################H] + +#----------------------------------------------------------------------------- +level "Level 40 (original)" +author "Broderbund" +size 26x16 +[| #################] +[| ########X ------#] +[| $ H# $ XH # $ #] +[#######HX####### XH ######] +[ $ HX $ XH ######] +[H######HX ##V### XH ######] +[H &$ X $ XH & ] +[#######HX ##VVV# ########H] +[ $ HX $ H] +[H#######X ##V### H] +[H $ X $ H] +[#######HX ##VVV# ##### H] +[ $HX $ # $# H] +[H#######X ##V### H## H] +[H & @ H# $ H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 41 (original)" +author "Broderbund" +size 26x16 +[ --$ --------&----- ----] +[ $H $#$ H- # -H $$$] +[@H $# #$ H- ### -H $$] +[# $# #$ H- # # -H $] +[ &V # # H- ## ## -H&] +[H# ### XXX- #$$$# #H] +[H # # $ HH### H] +[H - ### $H H##H# H] +[H - # $H H$$H ------H] +[H - $H HXXXXH H] +[XXH ---H H$ $H -----H] +[ H H######H H] +[ H###H H$ $H ----H] +[ H HXXXXXXXXH H] +[ H & H$ & $H ---H] +[#######XXXXX########H H] + +#----------------------------------------------------------------------------- +level "Level 42 (original)" +author "Broderbund" +size 26x16 +[ $ $ $ $ ] +[H## H### H#########H] +[H$ $ H $ H $ $ H] +[H##H###H #####X##X###X##] +[H H &H -------------- ] +[###H######H $ $& H] +[ H H X####XXXXX###H] +[ HXXXXX H X $ $ H] +[ H $ X H X XXXXXXXX H] +[$$XXX###X H X X $$ X H] +[##XXX###X H X $ X H###HX H] +[ $ $ H XXVXX H HX H] +[######## H X H &HX H] +[ $ $ X H X#######XXXX H] +[#####H XXXX####X $ $ @H] +[###$#H H########] + +#----------------------------------------------------------------------------- +level "Level 43 (original)" +author "Broderbund" +size 26x16 +[ ] +[ | |] +[ H#######################H] +[ H H## $ $ & $ ##H H] +[ H###H###############H###H] +[ H H H ### $ $&##H H H H] +[ ##H###H H#######H H###H##] +[ H H H H H H###H H H H H H] +[ H###H###H H $ H H###H###H] +[$H H H H H&HXXXH&H H H H$H] +[###H###H$HXHXXXHXH$H###H##] +[#H H H HXHXHXXXHXHXH H H H] +[#H## HXHXHXHXXXHXHXHXH ##H] +[#H HXHXHXHXHXXXHXHXHXHXH H] +[#HXH H H H H @H H H H HXH] +[###########H#$#H##########] + +#----------------------------------------------------------------------------- +level "Level 44 (original)" +author "Broderbund" +size 26x16 +[#########################|] +[ HHHHHHHHHHHHHHHHHHH |] +[ @ H HHH H HH H & |] +[###H HHH HH H HH H HHH###|] +[ H HHH HH H HH H H |] +[ & H HHH HH H HH H HHH & |] +[###H H H HH H###|] +[HHHHHHHHHHHHHHHHHHHHHHHHHH] +[ $ H $ H $ H $ H $ H $ H] +[HHHHHHHHHHHHHHHHHHHHHHHHHH] +[ H H H HH H HH H H H] +[ H H H H H H H H HHH H H] +[ HH H H H H H H H HH] +[ H H H H HH H HH H HHH H H] +[ H H H HH H HH H H H H] +[HHHHHHHHHHHHHHHHHHHHHHHHHH] + +#----------------------------------------------------------------------------- +level "Level 45 (original)" +author "Broderbund" +size 26x16 +[XXXXXXXXXXXXX | XXXXXXXXX] +[ &H H--- | H $ ] +[XXX|##XXX#V#XXX| HXXXX HX#] +[X--H H----H H #####] +[X H $ #$#H& H $ ##] +[$ VH H X#H XX####X#] +[X#VH-----H-----XH-------HX] +[#$ X H $HXXX H#] +[XXV# $$$H HX---- $ HH] +[ H HXH $ V#XH] +[###V# H @ HXH H] +[H---- HX##X##VXXH H] +[H$ #H H#H X#### H] +[HX--###H HXH # $ X H] +[H ###X#H & H H #XX#XX] +[#####XXXX#############X###] + +#----------------------------------------------------------------------------- +level "Level 46 (original)" +author "Broderbund" +size 26x16 +[ $ | ] +[####H & | ] +[ $ H H######H $ ] +[#######H######H ######] +[ H H $ $ ] +[ $ H H###########] +[#H#####H $ H ] +[ H $ HXXXXXXH $ ] +[#H#####H #####H#####H] +[ H & $ H H] +[ $ H###H#######XXXXXXX] +[###H#### H $ $ & ] +[ H H########H######] +[ H------H H ] +[ H @ H $ ] +[######################|###] + +#----------------------------------------------------------------------------- +level "Level 47 (original)" +author "Broderbund" +size 26x16 +[ XXXXXXXXXXX|] +[& & X $ X |] +[X------####H @X HX XHX###|] +[##### $ ##XX HX XHX###|] +[ ###### HX XHX |] +[##H ###H $ HX XHX $ |] +[ ###X#H H###XX XHX###|] +[ $ ##X#H H X XHX###|] +[#### ####H X XHX |] +[ $ #XH# ##X##HX XHX$$ |] +[## H##XX# $ XHX XHX###|] +[ #X##H ##XX#XHX XHX###|] +[ ###X##H $ XHX XHX ##|] +[ H## $###X#H#XHX XHX #|] +[ H# H $HX H $|] +[$H#X###X#####X##XX##X#####] + +#----------------------------------------------------------------------------- +level "Level 48 (original)" +author "Broderbund" +size 26x16 +[ $ ] +[ ------- ####H@ ] +[H $ H $ $ ] +[H HXXXX #####H#####] +[H H $ H ] +[H######H ####H H ] +[H H $ H&H#########H] +[H H HXXXX HXXXXXXXXXH] +[H $H# H $ HX $ XH] +[H H# ####H HXHXXXXXHXH] +[H $H# $ H HXHX $ HXH] +[H H# HXXXX HXHXXXXXXXH] +[H H# H $ HXH $ H] +[HH# ####H HXXXXXXXXXX] +[HH & | H & ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 49 (original)" +author "Broderbund" +size 26x16 +[ - - - - $ $ ] +[- - - - H - - H######] +[ -- -- H - - H ] +[ H -- H & ] +[ $ $ $ H - HXXXXXH] +[XXXXXXVXXXXXH- HX $ XH] +[ X HXHX$XH] +[ $X @ $ HXHX$XH] +[H########H#XXH####-HXHX$XH] +[H & H##HH HXHX$XH] +[H ## H##H $& XHX$XH] +[H ## ## H##XX#####HXH----] +[H ## ## H## H ] +[H ##$$## H# --$H #### ] +[H $$##$$ H## H# #H##$$##] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 50 (original)" +author "Broderbund" +size 26x16 +[H - H----] +[H H H X ] +[H H & H X$$] +[H $ H### $ $H####V#H###] +[H## H ######### HH#V] +[H H HHV] +[H H-----------------HH] +[H H H] +[H H$ & $ $H] +[H ####HXXXXXXXXX##V###] +[H--- H --- ] +[ &$ H H ] +[########H H $ H- $ ] +[ #####HXXXH### #$###] +[$ @ H H & #####] +[############H H#########] + +#----------------------------------------------------------------------------- +level "Level 51 (original)" +author "Broderbund" +size 26x16 +[##XX# |X#XX###X] +[#XX## |#XX###XX] +[ X#X# $ $ |#X X] +[H X##X###XH##X |#X #XH X] +[HX X#XX###XH ##$|X #XH X] +[H# X##XXH #### $#XH X] +[H##$ #XX#H ##XH$ ] +[HX#### X##H ------#XX#H] +[HXX#X##$ #XH $ #X H] +[H H## XX#XX# #X H] +[X##XXHX## $#X H] +[##XXXH#X##$ & $###X H] +[ $ HXX###VXXXXXV###XXH##] +[HX###XX & @ HX#] +[H###X H##XX#XX#X#XX##XXX#] +[H $ H & X#X] + +#----------------------------------------------------------------------------- +level "Level 52 (original)" +author "Broderbund" +size 26x16 +[ H ] +[ H $ & ] +[---- $ | XXXXXXXXXXXXH] +[H XXXXXX H] +[H ---- ----- HXXXX] +[H-------- H H ] +[ & $ H# H ] +[HXXXXXXXXXXXXXXXX# XXXXH] +[H HH] +[H $ $ & X H ] +[XXXX##XXXH #X#XXXXXXXX H ] +[ H H ] +[ $ H $ H ] +[HXXXXXXXXX XXXXXXX H ] +[H ------H ] +[H @ & ] + +#----------------------------------------------------------------------------- +level "Level 53 (original)" +author "Broderbund" +size 26x16 +[ ] +[ & & $ $|] +[ H############# H####] +[ H ########### H#####] +[H##### #$##$##$# H######] +[H###### &H#######] +[H############V######## ] +[H####### $ $ $ $##### $$ ] +[H#########V##V############] +[H & $###### ] +[H H#####H#####H -H#### $H] +[H H H H H H ### $H##] +[H H$$H$$H$$H$$H # $H####] +[H H#####H#####H $H######] +[H @ H########] +[H#########################] + +#----------------------------------------------------------------------------- +level "Level 54 (original)" +author "Broderbund" +size 26x16 +[| ############] +[| $ $ ############] +[#############H $ ] +[#########################H] +[ $ & & $ H] +[H#########################] +[H $ $ ] +[#########################H] +[ $ $ $ H] +[H#########################] +[H $ & & & $ ] +[#########################H] +[ $ $ $ $ H] +[H#########################] +[H $ $ @ ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 55 (original)" +author "Broderbund" +size 26x16 +[###########| #############] +[#---------#| #---------# ] +[ #$ H $# | #$ H $# ] +[ #$ H $# | #$ H $# ] +[ #$H$# | #$H$# ] +[ #H# |XXXXX##H# ] +[ @ #H# |X $ #H# & ] +[###H#H#####V#######H#####H] +[ H H & H H] +[H##X#H#############H#X####] +[H---#H#-----------#H# ] +[H $# H #$ $# H # ] +[H$# $H$ #$ $# H # ] +[H# $#H#$ #$ H### H #$ ] +[H $##H$#HH#H#X# & H $ ##] +[#########H H $############] + +#----------------------------------------------------------------------------- +level "Level 56 (original)" +author "Broderbund" +size 26x16 +[$$----$$$ $$$-----------$$] +[## ###H### ##] +[## ###H### ##] +[## ###H### $$$ ##] +[## ###H### ### ##] +[## ###H### ### ##] +[## ###H### ### ##] +[## ###H### ### ##] +[## ###H### ### ##] +[##$--$###H###$--$###$--$##] +[###$$####H####$$#####$$###] +[#########H################] +[######## H ####### #######] +[ ###### H ##### ##### ] +[ & @H & ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 57 (original)" +author "Broderbund" +size 26x16 +[|#########################] +[|------------------------ ] +[|#XXX#XXX#XXX#XX#XH#X---#H] +[|# $ $ $ H $H#H] +[|$HXXXXXXXXXXXXXXXXXXXXHXH] +[|#H#----------------X $H#H] +[|$H# XXXXXXXXXXXXXXXXX###H] +[|#H# X $$$$$$$$$$$$ $#$H] +[|$H# X###XXXXXX#XXXXXH###H] +[|#H# & H$#$H] +[|$H#XXXXXXXXXXX##XXXXH# #H] +[|#H------------------ H#H] +[|#XX##XXHXX#X#XXHXXXXXXH$H] +[| & H XX H & $H#H] +[XXX#X###XXXXHXX#X#XX##XX#H] +[@ H H] + +#----------------------------------------------------------------------------- +level "Level 58 (original)" +author "Broderbund" +size 26x16 +[#################### |] +[ @##--- XX $ |] +[ #X $ HXX######HH H#H H |] +[ # H XX# HH$H H H |] +[ #H####X##$ # HH H H#H |] +[ H# X## HH H H H |] +[$ H# $ #X# H# H H H H |] +[#HH##V#X###X# H#$#|##H#H |] +[#H & H#V#|# H H |] +[#H##X#######XHHH #|# H H |] +[#H #X#######XHH #|# H H&H] +[ H X $ XH #|#HH###H] +[ HH#X#######XH $ #|#H& H] +[ #H#X#######XHXXX#|#### H] +[ #H# $ XX# | # H] +[ $H #XXXXXXXXX# & | ####] + +#----------------------------------------------------------------------------- +level "Level 59 (original)" +author "Broderbund" +size 26x16 +[ -- $ -$ $ ] +[ H ## H ## ##H ] +[ H $& H H $] +[ $H-- ##$H &$ HH#] +[##H H$& #H ## $ H ] +[ $ H## H ## H ] +[ ## H- --&$--H H ] +[ $ H ## $ $- H$] +[ ## H ## ## H$H##] +[ - $H $ H## ] +[ H ##H ## $ H ] +[ $ H $ ## $ H$ ] +[H##H ## ## H## ] +[H ] +[H @ ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 60 (original)" +author "Broderbund" +size 26x16 +[ ----- ] +[ ----H &$ $ ] +[ ----H & $ #####H] +[ ---H $ ##### $ H] +[H @$ #### $&#V#H] +[H V#V ## #### $ #V### #H] +[H $ $ $ # $ ##V# $ #H] +[H ## V#V # #### $###H#H] +[H $ $ $ # # $ #V#V #H#H] +[H ### V# # # ##V# $ #H#H] +[H $ $ $ # # # $ ##H#H#H] +[H #V V## # # # #####H#H#H] +[H $ $ $ # # # # #H#H#H] +[H ##V V# # # # # $ #H#H#H] +[H &# # # #####H#H#H] +[########### H H H] + +#----------------------------------------------------------------------------- +level "Level 61 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | ] +[ $ & $ XHX --------@ ] +[HX###X# XH$ ### ] +[HX XHX $ $] +[HX--- XHX ####--- H] +[HX $XHX $ $ H] +[H $X##XXHX### H### H] +[HX#XX XHX &$ H# H] +[HX------$HX ######## H] +[HX $ XHX $ $ H] +[HX X##XHX--####-- H# H] +[HX$ XHX $ H H] +[HX## XHX ##### H] +[H & H H] +[X###X###XXXX###X####XX#XXX] + +#----------------------------------------------------------------------------- +level "Level 62 (original)" +author "Broderbund" +size 26x16 +[#|####|#####|#####|#####|#] +[ |$& | | $ | $ | ] +[H########V####V##########H] +[H#$ &$ $ #H] +[H#####V########V#######H#H] +[H# $ $ #H#H] +[H#H####V####V#####V##H#H#H] +[H#H# #H#H#H] +[H#H#H#$ & $ #H#H#H] +[H#H#H###V##V###V#####H#H#H] +[H#H#H $ $ H#H#H] +[H#H###V############V###H#H] +[H#H $ $ H#H] +[H###V####V####V######V###H] +[H & $ @ $ & H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 63 (original)" +author "Broderbund" +size 26x16 +[ & ] +[#########################|] +[$& # $ # $ |] +[##H# #H#H######## #H# ##H#] +[##H#H#H#H# $ # #H# ##H#] +[##H#H# #H# #### # #H# HH] +[$#H#H#H#H#H#@ # # #H# ###H] +[ H#H#H#H#H## # # #H# H H] +[H#H#H#H#H#H $# # #H# H###] +[H## H#H#H###### # #H# H H] +[H# #H#H#H $ # #H -###H] +[H -#H#H########## #H# H H] +[H# #H#H #H# H###] +[-# #H##############H# H H] +[ H & H# ###H] +[##################### & H] + +#----------------------------------------------------------------------------- +level "Level 64 (original)" +author "Broderbund" +size 26x16 +[X| |X] +[X| &$$$$$$$$ $$$$$$$$$& |X] +[XXXXXXXXXXXX|XXXXXXXXXXXXX] +[ $ $ | $ $ ] +[ XHXXXX | XHXXXX ] +[ H$ $ | H$ $ ] +[ XXXXXXHX | XXXXXXHX ] +[ $ $H | $ $H ] +[ XHXXXXXXXX | XHXXXXXXXX ] +[ H $ $ | H $ $ ] +[XXXXXXXXXXHX|XXXXXXXXXXXHX] +[ $ $ H | $ $ H ] +[XHXXXXXXXXXX|XXXXXXXXXXXXX] +[ H ] +[ H $ $ @ $ $ &] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 65 (original)" +author "Broderbund" +size 26x16 +[ ####### ] +[--------$ &| ###### ] +[H H#H---- | ######H] +[H HV#VH $H$ | ## #H] +[H-----HV#VH ###H | #$ #H] +[H HV#VH&###H | ###H] +[H& HHHHH ###H | ##H] +[H---- XVHVX ###H | #H] +[#$ H XVHVX H ||H] +[##$ H XVHVX H--H---------H] +[###$H XVHVX H ] +[####H&XVHVX H------H##$###] +[ H XVHVX H HX######] +[ H XVHVX H HX#######] +[ H @H H HX#######] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 66 (original)" +author "Broderbund" +size 26x16 +[######HH----------HH######] +[#####HH - - HH#####] +[####HH #&&# HH####] +[###HH - #### - HH###] +[##HH - ###### - HH##] +[#HH----- ######## -----HH#] +[HH - ####$$#### - HH] +[H ############ H] +[HH - ####$$#### - HH] +[#HH - ######## - HH#] +[##HH - ###### - HH##] +[###HH - #### - HH###] +[####HH - - HH####] +[#####HH HH#####] +[######HH& @ &HH######] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 67 (original)" +author "Broderbund" +size 26x16 +[| ] +[| # & # & & ] +[|-----$H#H ##H##||#||##H ] +[H #H #H# H# $# $# H ] +[H @ # # H# H# # H ] +[##### ## H# # # H ] +[ # $# H# $# # H ] +[ # # HHH # # ####H] +[ $# $# #HH# ## V H] +[## # $# H# # # # H] +[# $# # H# # # #$ H] +[ # $# H# $# H# #$ # H] +[ $# # H# # H # # # H] +[ # $# H# # H #$ # #H] +[ # HH $ H # H] +[ H################## H] + +#----------------------------------------------------------------------------- +level "Level 68 (original)" +author "Broderbund" +size 26x16 +[XXXXXXXXXXXXXXXXXXXXX| ] +[ & | ] +[ H#X##XX#HX | ] +[ H |HX#X##XX#| ] +[ ##XH H|H# # &#-------] +[$ H $|H|## # X# $] +[ H H|H|# # # &] +[H H H|H|# $#@ # #] +[H H H|X## ## # $#] +[HXXXXV#XX|X # # ##] +[H --------X-----# # $ #] +[H $ H ## # ###] +[H HXVXXXHXXX#H# # $# ] +[H HX XHX #H####V#X# $ ] +[H HX XHX$ #H ##X] +[H $HX & XHX#####XX###X####] + +#----------------------------------------------------------------------------- +level "Level 69 (original)" +author "Broderbund" +size 26x16 +[H & # ------------] +[H#### #H ] +[H#### #H #X#X#X#X#X#] +[H#### #H $ $ $ $ $ $] +[H##$# #H#V#V#V#V#V#V] +[H#### $ & #H#V#V#V#V#V#V] +[H############H------------] +[H############H X X X X X] +[H @ & H #V#V#V###] +[H#######H#######H V###] +[H#######H #####H####HV###] +[H#######H#$ ###H####HV###] +[H#######H###$ #H & HV###] +[ H##### H####HV###] +[ $ $ H#######H####HV###] +[################H $$ HV###] + +#----------------------------------------------------------------------------- +level "Level 70 (original)" +author "Broderbund" +size 26x16 +[ |] +[ |] +[ &-$$$-|] +[ $- H$###$H] +[$H# $- $H#####H] +[#H # $ #H##$##H] +[ H $- #H-H#####H] +[ H # $ -H $###$ ] +[ H #H ] +[ H $ H $$$$ ] +[ H # $ -H $####$ ] +[ H #H ####HV ] +[ H $- H ###HV# ] +[ H # $-H ##HV## ] +[ H $# H #HV### ] +[ H @ # H & HV#### ] + +#----------------------------------------------------------------------------- +level "Level 71 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | & ] +[ | H#####H ] +[$H####H#H& $ H# #H ] +[H#####H#####H##H######H##H] +[H XH $ XH XH X# #H $H] +[H ###XH X# XH XH $X# #H #H] +[H $##XH $XH XH # # #H #H] +[H ###XH # #XH XH XX #H #H] +[H $XH X H$#H ##$ #H&$H] +[H#####H#####HV#H######H##H] +[H$------ $$ H & ## X$H] +[XXH ##XXX##HXX#$ $XH] +[ H###$#XXXXX#HXXXXXXHXXXH] +[@ H#$##$$$$$$ H$ H H] +[XXXXX####XXXXXXX##########] + +#----------------------------------------------------------------------------- +level "Level 72 (original)" +author "Broderbund" +size 26x16 +[| ] +[| -----------------##] +[H $& H #] +[H##V#### H #] +[H # H $&H ## $#] +[H $ H # $ --H###H######] +[H###H$ ##### $ H H ] +[ H#########VH H $ ] +[H H## $ ###VH $#H-----#] +[H###H#########VH###H $ H #] +[H #--------H#$#HV##H #] +[H$&H # $ H###H H #] +[###H # $ ## H###H H #] +[ H # $ ## H###H H #] +[ H @#### $ H###H &H #] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 73 (original)" +author "Broderbund" +size 26x16 +[ ] +[ |||||||@| |& ] +[ & | || ||X ] +[ $H$ | || ||XXX ] +[ $HHH$ | || ||XXXXX ] +[$HHHHH$ | |||XXXXXXX] +[HHHHHHH | $& $ |---HHH ] +[ H ############ H ] +[ $X$ # $ $ # H ] +[ $XXX$ # -------- # H ] +[ XXXXX # H H # H ] +[ XXX # H H # H ] +[H#####H#$H & H$# H ] +[H H############ H ] +[H H H H H ] +[H#####H############H#####H] + +#----------------------------------------------------------------------------- +level "Level 74 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | XXXXXXXXX] +[XXXX|XXXXXH----H ] +[ | H @ H & ] +[####H#####################] +[#H H H### #### ] +[HH#####H### ## ###########] +[H###### H## $# ### ## ## ] +[H# ### #H## ## ### $### $ ] +[H## $ ##H## ### ## $## ] +[H#######H#########V#######] +[H # #$ HH &H] +[H####### H########H######H] +[H $### H ##H H] +[H & H $ ##H $ H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 75 (original)" +author "Broderbund" +size 26x16 +[ $ $ ] +[ $ $ ##H## $ $ $ ] +[ ##H## H ##H## #H#] +[ H H H H ] +[ H H H H ] +[ H &H $$ H H ] +[ H H ## H --- H] +[ H H H H ] +[ H H ----- H H@ ] +[ H ----- &H H ##] +[ H $$ H H ] +[ H ## H H ] +[ & H H H & ] +[#####VVVVVVVVVVVVVV######H] +[ H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 76 (original)" +author "Broderbund" +size 26x16 +[############## |] +[ # |] +[ ------------HH#######$ |] +[ H# $ # #--H] +[$ $& @ H# # #& H] +[H######HXXXXXX#XX H # H] +[H #H ### H H] +[H$ #H------- & #H H] +[H ##XH #######H H] +[H ##$XH ### #H####] +[H # XH $##$# $$ #H## #] +[H# XH ## #######H# # ] +[H#$ XH ## #-----#H## #] +[H HHH# # $ #H#$# ] +[H H#H #H## #] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 77 (original)" +author "Broderbund" +size 26x16 +[ --- $$$$$$$ --- ] +[H ################## H] +[H XX##################XX H] +[H ################## H] +[H&XH##################HX&H] +[XXXH# # # ###HXXX] +[ H#$$$$#$$$$#$$$$###H ] +[ H##################H ] +[ H##################H ] +[ H##################H ] +[ H### # # #H ] +[ H###$$$$#$$$$#$$$$#H ] +[ H##################H ] +[ H##################H ] +[ H##################H ] +[ H @H ] + +#----------------------------------------------------------------------------- +level "Level 78 (original)" +author "Broderbund" +size 26x16 +[# #|] +[# $ & ----------$#|] +[############HH & $ H##|] +[### HH########## |] +[#### $ & HH ## |] +[############HH $ ###H |] +[###### HH####### H |] +[ $ ## $ HH ###V#H |] +[H###########HH$ ## H |] +[H# # #### HH#### $ H |] +[H H#H# $## HH #####V##H |] +[XXH H#H####@HH # $ H |] +[XXXXH H# ###HH####V####H |] +[XXXXXXHHH# #HH# H |] +[ H H HH H |] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 79 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ & X | & $] +[HXXXX XXXXXXXHXX #|#H###] +[H --- HX$##H#|#H###] +[#H## ## H#& H ###H#|#H#$#] +[ H ##$# H # H## H#|#H###] +[H ####VH #H H###|#H ] +[H @ H # H# | ###H] +[H####### # $# $H#H######H] +[H#######V# # ####H## H] +[H#######V# $##H #####] +[H#$ ##V#----H# #H----- ] +[H# $##V#H # #$ # #H] +[H#######V#H #######H##$#H] +[H ##$ H ## H ###H] +[H#########H########## H] + +#----------------------------------------------------------------------------- +level "Level 80 (original)" +author "Broderbund" +size 26x16 +[ -----------$ ] +[XXXXX ## #XXXXXX#H ] +[X----- $$ # #H ] +[XH ###V # $#H ] +[XH$$ $ $ ######V#H ] +[XXXH $ #V## &HH ] +[ H $ $ &-- H ] +[ H #XXXXXXXXX#-- H ] +[ H$& $ #& $ # H ] +[ H####H######V#### H ] +[ # #H H ] +[ # #H H ] +[ #$$#H H ] +[ ##V#H H ] +[ H & @ H ] +[###XXXX###XXXX###XXXX###XX] + +#----------------------------------------------------------------------------- +level "Level 81 (original)" +author "Broderbund" +size 26x16 +[| ] +[| ] +[XXXXXH HXXXX] +[# H & & H ] +[# H#######XXX#####H ] +[# H H ] +[# --H H ] +[# $ $H $#$ $$$H ] +[# #$#H-- # # $$$ ###H-- ] +[# #$#H$ $--$# ### #$#H$ $-] +[# ###H#$# $#$ $$$ ###H#$# ] +[# #H$#$ ### ### #$#H$#$ ] +[# #H#$# ###H#$# ] +[# H-H H-H ] +[# H @ H ] +[##XX#########XXXX#########] + +#----------------------------------------------------------------------------- +level "Level 82 (original)" +author "Broderbund" +size 26x16 +[XXXXXXXXXXX | XXXXXXXXXXXX] +[--------H#X-|-X#H---------] +[ $ H#--|--#H $ ] +[ $ ##H--$|$--H## $ ] +[ $##V-HH#X#|#X#HH-#V# $ ] +[ $##--H-#V-H|H-V#-H--###$ ] +[$##--H-----H|H-----H---##$] +[V---H------H|H------H----V] +[---H&------H|H------&H----] +[ H######VH@HV######H ] +[ $ H ### H $ ] +[H H & #$# & H H] +[H--H#V#####H H#####V#H---H] +[H$ H H H H $ H] +[H H $ H H $ H H] +[########X#######X######XXX] + +#----------------------------------------------------------------------------- +level "Level 83 (original)" +author "Broderbund" +size 26x16 +[----$ $$@#|] +[ #H H####|] +[ #H HV####|] +[ #H H#V# #|] +[ #H H##V#$ #|] +[$ & #H H#$#V#VV#|] +[### #H H# H#V# #|] +[$ #$ #H$ H# $H#V# #|] +[##H # ##H H####H#V# #|] +[$ #H #$ #H$&H# $ $H#V# #|] +[#H #H # ##H######H#V# #|] +[$#H #H #$ #H $ $ -H#V# #|] +[H #H #H # #H##### H#V#VV#|] +[#H #H #H H#V# |] +[ H H H & H |] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 84 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | ] +[& $#$ |#$ ] +[#####H#######H#H#########H] +[$ #H $ H#H # H] +[###H#####H########H#H#####] +[$ H H & H#H $] +[#H#############H##########] +[$H##$ # $#H & #$ ] +[#########H#######H########] +[##H &H##$ ## H ## $#] +[##H####H########H##H######] +[$ H####H# $####$H##H ##] +[##H####H########H#####H###] +[##H #H # @ H # H $] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 85 (original)" +author "Broderbund" +size 26x16 +[ & $ ] +[ $ ######H# $ ] +[ ###V#### H#####V# ] +[ # # H# # ] +[ # &$ # H# # ] +[####### $ #$ #H#####$$# ] +[# ###V#####H #V####] +[# # $ #H &$ - #] +[# # H########### H#] +[# $ $# H# $ H#] +[# ##### H# $ H#H H####] +[### # $#H#### H###V# ] +[ # $ ####H # $H# ] +[ ##### #H ###V# ] +[ H @ ] +[X#X#X#X#X#X#X#X#X#X#X#X#X#] + +#----------------------------------------------------------------------------- +level "Level 86 (original)" +author "Broderbund" +size 26x16 +[| |] +[|------------------------|] +[HH HH] +[H #V## ###V## ###### H] +[H # ## # # # V H] +[H # ## # # H] +[H # # # # H] +[H # $# # $ # H] +[H # ## # ## # $ H] +[H #$ ## # $# #$ $# H] +[H #### ###V## ##V### H] +[H @ H] +[H H###### ###### #H#### H] +[H H# $# ######H#H##$# H] +[H&H# #&## $##H H#### H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 87 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | ] +[ H$ $H $H $H ] +[ $H H$ H$ H$ ] +[ H$ $H $H $H ] +[ $H H$ H$ H$ ] +[ H$ $H $H $H ] +[ $H H$ H$ H$ ] +[ H$ $H $H $H ] +[ $H H$ H$ H$ ] +[ H$ $H $H $H ] +[ $H H$ H$ H$ ] +[ H$ $H $H $H ] +[ $H H$ H$ H$ ] +[@H$ $H &$H & $H &] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 88 (original)" +author "Broderbund" +size 26x16 +[ --------# & ] +[H # $ H###H # #H] +[H VVVVVV ####HX HX H # #H] +[H VVVVVV # $HX HXHXH # #H] +[H VVVVVV #H###X HXHXH # #H] +[H VV$$VV #H $ X HXHXH # #H] +[H VVVVVV ####HX HXHXH # #H] +[H VVVVVV # $HX HXHXH #$#H] +[H &#H###X HXHXH ##VH] +[H#########H $ X HXHXH H] +[H############HX##XHX#####H] +[H######### $HXXXXHXXX###H] +[H##$$#####H###X $ |$ X$##H] +[H########$HX#XXXXXXXXX###H] +[HXXXXXXXXXX $ &$ H] +[H @ H##############] + +#----------------------------------------------------------------------------- +level "Level 89 (original)" +author "Broderbund" +size 26x16 +[|#XXX#XX##X##XX#X XX#XX##X] +[H|||||X|X#XX#|X||||||XX###] +[H @ $|X| $$$ | | & | $ |] +[HX#X#|X|#X##XH#HX###H####|] +[H $ |X| $$$ H H $##H###X|] +[HX#X||X| ### H H XX$H$##$|] +[H||| $X| H$H #XHX#XX|] +[H ##X| $ HXH $ H----|] +[H$ &| X| ### HXH #XH $X#] +[H####HX| # H$H # H ##$|] +[H X HX||||||HXH # H XH] +[H X H---------H$&# HX$$$H] +[H X$HX####H $XH##########] +[H X#HX #####X#X-------H] +[H $ H $ $ & $$$H] +[######X#XXXXXXXXXXXX#XXXXH] + +#----------------------------------------------------------------------------- +level "Level 90 (original)" +author "Broderbund" +size 26x16 +[ H | ] +[ -- H | ] +[$ $ -- H --H $|& ] +[####H-- H & ---#V##H#H ] +[ H X#V#H ---$#$ |#H ] +[VV###H $ H-HXX X######H ] +[V$ H X H XXXX --H ] +[ V$ H $H $ HX ] +[ #$ H#V##HXXXXXXH#VXHX ] +[ H#$H H $ H HX ] +[ H VHX H#V####H##XHX ] +[ H -H $ H $ H XHX ] +[ HX $ X H####V#H X$H$X ] +[ H X H $ H XXHXX ] +[ H H##V###H &H ] +[##########H & @H########] + +#----------------------------------------------------------------------------- +level "Level 91 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | ] +[ | ] +[ ----- & H#H & -----] +[ H---H#$H#H$#H---H ] +[ H#$#H H#######H H#$#H] +[ H### H-H# #H-H ###H] +[ HH# H###H #HH] +[ H# H# #H #H ] +[ H# H###H #H ] +[ H# H# #H #H ] +[ H# H###H #H ] +[ H# H# #H @ & #H ] +[ H########H###H########H ] +[$ H# $ #H $ H# $ #H$] +[XXXXXXXXXXXXXXXXXXXXXXXXXX] + +#----------------------------------------------------------------------------- +level "Level 92 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ $ #&#|# ] +[ H--H########## #|# ] +[$ ----H # $ # #|# ] +[#H # ##### #|# ] +[##H & # $ #|# ] +[###H $ # ---- #|# ] +[####H ----#$ $# H | ] +[XXXXXXH ###### H--| ] +[ H ###### H #####] +[ H ###### H #$ & ] +[ H ###### H ####H] +[ H H H] +[ --H H H] +[& $# H @ H H] +[#### H##$#########H ###H] + +#----------------------------------------------------------------------------- +level "Level 93 (original)" +author "Broderbund" +size 26x16 +[ || ] +[ & HHHHH $$||$$ HHHHH & ] +[ HHHHH H######H HHH H ] +[ H#H H H H $ H H H H#H ] +[ H#H H H H######H H H H#H ] +[ #H H H-H @ $ H-H H H# ] +[ $X H X-########-X H X$ ] +[ VH H H-H######H-H H HV ] +[ HVH H H-H######H-H H HVH ] +[ HHH H H H#VV#H H H HHH ] +[ HHH H H H#VV#H H H HHH ] +[ HH H H #$$# H H HH ] +[ HHH H H HHH ] +[ HHHH HHHH ] +[ HHH HHH ] +[ &H##########H& ] + +#----------------------------------------------------------------------------- +level "Level 94 (original)" +author "Broderbund" +size 26x16 +[$ #############|##########] +[H#--- - $#|# ] +[H#$# #### #####|#H###H###H] +[H#$# # # $#|#H###H###H] +[H#$# #$$#######|#H #H&$#H] +[H#$# ##########|###H#H###H] +[H#$# $ & | #H#H###H] +[H#$#####H####$ | $#H#H H] +[H#$# H #######H#####H] +[H#$#H###$##H $ #H $ #H] +[H#$#H# $ #######H#######H] +[H#$#H H##H&$ #H $ #H] +[H#$############H#######H#H] +[H#$#$ # $ # $ H$ # $ H#H] +[H#V#H#H#H#H#H######H#####H] +[H $ H#H$H#H$H##@ $ H $ H] + +#----------------------------------------------------------------------------- +level "Level 95 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | ] +[ | ----- -----H] +[ &H - H --&H H] +[V#H---H #V## H# #H ##V##] +[V# H##V### H# #H ##V# ] +[V# H##&- H# #H ## ] +[V# H##H ## H# #H- # ] +[V# $ H##H$## H#$ #$HVV$@ ] +[V --H-H##H ## H# # H#### ] +[## HH ##H # H# # H#### ] +[##HH ##H V -H# # H## ] +[##H ##H ## # # H## ] +[##H $--##H $ # $# H $ ] +[#####H ######H ##V# H####H] +[#####H $#### H $#V$ H#####] + +#----------------------------------------------------------------------------- +level "Level 96 (original)" +author "Broderbund" +size 26x16 +[ - & ### & $ ### ] +[H H####H###H###### ######H] +[H H####H $H###$## ###$##H] +[H H#$$#H########## ####H] +[H #####H -------------H] +[H #H& $ $ ] +[H#V#H #H####V#######H$ $ ] +[H$ #H #H---- -----HXXXXXXX] +[## #H #H $ $ H @$ $ ] +[ $H #H####V#####H######H] +[##HXX #H----------H H] +[##H $H $ X#####H H] +[##H#############|X $ H H] +[$#H# |X####V# H] +[##H# $ $ |X & H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 97 (original)" +author "Broderbund" +size 26x16 +[ HH---HHHHH####] +[ H##H--H$$ H####] +[ H####H HH$H H H] +[ H######H HH$H$H] +[ H######H HHHHH] +[ H#X#XVXH H H H] +[ H$X#XV$H H H H] +[ H#X#XVXH H$H$H] +[$--------H#X#XVXH HHHHH] +[H$ H$X#XV$H H H H] +[#H$ H#X#XVXH H H H] +[##H$ H#X#XVXH H$H$H] +[###H$ H$###V$H HHHHH] +[####H$ H######H H H H] +[#####H$ HX# #X #XH @H$H$H] +[######H&HX# #X #XH&H######] + +#----------------------------------------------------------------------------- +level "Level 98 (original)" +author "Broderbund" +size 26x16 +[| ] +[|XXXX XXXXXXXXX#XXXXXXXXX$] +[| $ $---- --------H] +[| H## ##### ##H] +[| $ H $# # $#$H] +[| ###H $ @ ## #V##XH] +[| $ H#####H # & H] +[| ### H# #H #---H####] +[| & H#$ #H # H--- ] +[| H#########H### H $ ] +[### H#$ # $ # # H ###] +[$ ##H######### # H # ] +[####H---$$X$$#$ ##XXXHX##] +[ #H ###X#####H# H $] +[ $ #H $ HH & H#H ] +[####H############H########] + +#----------------------------------------------------------------------------- +level "Level 99 (original)" +author "Broderbund" +size 26x16 +[ --- $ $ --- X #H] +[## #H H###H H& ##X H] +[ ## #H H#########H ##X #H] +[## #H####$#$#####H #$X##H] +[$##$#H & H #H] +[###############V#########H] +[ $ & $ @ & H] +[XXXXXXXXXXXXXXH###########] +[ ----------- XH ] +[H - HXH---------- ] +[H - - HX## ## ## ##H] +[H - # - HXXXXXXXXXXXXH] +[H - ### - H------------H] +[H - ##### - HV#V#V#V#V#V#V] +[H- ##$$$## -HX ] +[H ######### HX & ] + +#----------------------------------------------------------------------------- +level "Level 100 (original)" +author "Broderbund" +size 26x16 +[ & & &- ] +[ H###### H##H] +[ H# # H##H] +[ H###### # H##H] +[ H # # H##H] +[ H###### #$$$# H##H] +[ H# # ##### H##H] +[ H##### #$$$# H##H] +[ &H# # ##### H######H] +[##### #$$$# &H# #H] +[# # ##### H###### #H] +[# #$$$# H# # #H] +[# ##### H##### $$$#$$$#H] +[#$$$# H#XXXXXX#XXX#XXH] +[##### H##### @ H] +[ H###################] + +#----------------------------------------------------------------------------- +level "Level 101 (original)" +author "Broderbund" +size 26x16 +[H H] +[H H#$##H H##$#H H] +[H$& H####H H####H $H] +[###H H####H----H####H H###] +[ H H##$#H H#$##H H ] +[ $&H H####H H####H H$ ] +[H### H####H H####H ###H] +[H H#$##H----H$###H H] +[H$ H####H H#$##H $ H] +[###H H##$#H H####H H###] +[ H H$###H H##$#H H ] +[ $ H H####H----H####H H $ ] +[H### H#$##H H###$H ###H] +[H H####H H#$##H H] +[H @ H##$$H & H####H & H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 102 (original)" +author "Broderbund" +size 26x16 +[--------- H ----- ] +[ H H H ] +[ ------H $ H H ] +[ H $ & ### H H ] +[ H #### H --- H $$--] +[ H H $ H ## ] +[ H--- $ H X H $] +[ H ## H H #] +[ H H XXX###X#] +[ H H -- ] +[ $&$ H H X X] +[ ### H---- H XXXXXX X] +[$ $$ H $ $ $&X] +[X XX H # ########] +[ @ H ] +[####XXX#########XXX#######] + +#----------------------------------------------------------------------------- +level "Level 103 (original)" +author "Broderbund" +size 26x16 +[-----------------------H ] +[ $ $ $ $ H ] +[#### #### ###V ##V# H ] +[ $ $ $ H ] +[# #V## ##V# V### # H ] +[ $ $ $ $ H ] +[#### #### ###V ##V# H ] +[ $ $ $ H ] +[# ##V# #V## V### # H ] +[ $ $ $ $ H ] +[#### #### ###V ##V# H ] +[& @ & H &] +[########################|#] +[########################|#] +[###################### | ] +[###################### &|&] + +#----------------------------------------------------------------------------- +level "Level 104 (original)" +author "Broderbund" +size 26x16 +[ & |] +[ $ $ |] +[ H###H ##H## H###H |] +[H# $ #HH#HHHHHH##HH# $ #H|] +[H#####H##HHHHHHH#H######H|] +[ & HHHH$HHHH |] +[########HHHHHHHHH########|] +[##$## #HHHHHHH# ##$## |] +[ ### #HHHHH# ### |] +[ # #HH## # |] +[ #H# |] +[ #H# |] +[ #H# |] +[ #H# |] +[ & H @ |] +[#########################|] + +#----------------------------------------------------------------------------- +level "Level 105 (original)" +author "Broderbund" +size 26x16 +[###XX####################|] +[ $ X $ & @ #|] +[H#H X#V#H######V####### #|] +[H##H V#HH##$--------$ #|] +[H ##H V##HH##$ $ $##H#|] +[H ##H ###HH##$ $## H#|] +[HH ##H ##HHH##$ $## HH|] +[HHH$ #HH #H#HH## ## #HH|] +[HHHH H#H H##HH#V## #HH#|] +[$HHHH&H##HH###HHV# $HHH$#|] +[HH$ HH ##H ###HV #HHHH#|] +[##H####$ ##H ##H HHHH&H#|] +[HHHHHHHH #HH HH&HHH$ H#|] +[H HH $ H H#HHH#HH####H#|] +[$ H#H####H HHH$ H |] +[####HHHH$H#####HH#########] + +#----------------------------------------------------------------------------- +level "Level 106 (original)" +author "Broderbund" +size 26x16 +[XXXXXXXXXXX| XX X#X] +[#######X##X| #X #X#] +[ $ #X#XX| XX # ] +[HX###V# X| & X $# $] +[H#### ---H##XXV#####HX H] +[H# $# ---XXH# VX####H# H] +[H###--- XXH#---VX####HX#H] +[H##--- HX $ ##XH##H] +[H#--$ #X#H# V##XX#H##H] +[H-- X------H ---- ##H #H] +[ X#& $ XHV##X@ $ H##H] +[##V#X## X#XHV##X#XX#X H] +[##V#X XHV & $ XX####] +[##V#X------HV## ####X $ #] +[## $ XH #####] +[#X####X#H H H###X#######] + +#----------------------------------------------------------------------------- +level "Level 107 (original)" +author "Broderbund" +size 26x16 +[ --------- @ --------- ] +[H ---- ###### ---- H] +[H --- ########## --- H] +[H -- ############ -- H] +[H - #####$$$$##### - H] +[H - ############## - H] +[H ################ H] +[H ##$$$$####$$$$## H] +[H ################ H] +[H ######$$$$###### H] +[H ############## H] +[H - ############## - H] +[H - #$$$$##$$$$# - H] +[H -- ########## -- H] +[H&$$---$ ###### $---$$&H] +[########H$$$$$$$$H########] + +#----------------------------------------------------------------------------- +level "Level 108 (original)" +author "Broderbund" +size 26x16 +[########## ######XX###|] +[-------------------- ## #|] +[ H#########H |#-----H----|] +[@H$X$$$$ H |#$ $$H $|] +[#H#####X###H |###H###V#H#|] +[ HHHHH X $H |#$ H-----H |] +[$ X$H $$#H |#X H XXX H$|] +[######V####H |#$ H& $$HXH] +[ $X$$ X #H |######H####H] +[ XXXX X #H-H#$ H $$|] +[ $$$ $$X$ #H&H#X$ H ###H] +[H###V####H########H######H] +[H--------H##$-----H-X ---H] +[H $ $$$ H H $ $ H XH$ $#] +[#H##HX#H###VH##X#V#####H##] +[$H$$H& H H $$H$$] + +#----------------------------------------------------------------------------- +level "Level 109 (original)" +author "Broderbund" +size 26x16 +[HH #####&HXX XXH&##### HHX] +[HXHH $ HHXHHHHHXHH $ HHXHH] +[$HXH#H#HXH$#H#$HXH#H#HXH$#] +[# HXHHHXH # H # HXHHHXH #H] +[ #HHXHXHH# H H #HHXHXHH# ] +[H# HHHHH #H # H# HHHHH #H#] +[H#H H#H#$#H#H H#H@] +[H# HHHHH #H # H# HHHHH #H#] +[ #HHXHXHH# H H #HHXHXHH# ] +[V HXHHHXH # H # HXHHHXH #H] +[$HXH#H#HXH$#H#$HXH#H#HXH$#] +[HXHH $ HHXHHHHHXHH $ HHXHH] +[XH ##### HXXHXXH ##### HXX] +[XH H $ H HXXHXXH H $ H HXX] +[XH H#H#H&HHXHXHH&H#H#H HXX] +[HXHXHHHXHXHHHHHXHXHHHXHXHH] + +#----------------------------------------------------------------------------- +level "Level 110 (original)" +author "Broderbund" +size 26x16 +[ X------ --- HH##H |] +[$ & $X-----$## HH##HH |] +[###H#X $## HH##HH$ |] +[ H X $## HH##HH$ XX|] +[$ H$X $## HH##HH$ XX |] +[###H#X $## HH##HH$ XX |] +[ @H X$## HH##HH$ XX $$|] +[###H$X## HH##HH$ XX H## ] +[###H#X# HH##HH$ XX H$$ ] +[#$#H X $$HH& HH$ XX H#### ] +[###H$X##########HX H$ &$ ] +[$##H#X----------HX H##### ] +[###H$X $ H X H$ $ ] +[#XXXXX## H #### X H##### ] +[ &H##$$##X H$ $ ] +[##########X######X #######] + +#----------------------------------------------------------------------------- +level "Level 111 (original)" +author "Broderbund" +size 26x16 +[ HHH ] +[ HHHH ] +[ HH ] +[ & HHHH & ] +[----------HHHHHH----------] +[----------HHHHHH----------] +[ ---------HHHHHH--------- ] +[ -------HHHHHH------- ] +[ -----HHHHHH----- ] +[ --HHHHHH-- ] +[$ $ $ $ $ HHHHHH $ $ $ $ $] +[ HH&@HH ] +[##########HH##HH##########] +[##########HH##HH##########] +[ $ $ $ $ H H $ $ $ $ ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 112 (original)" +author "Broderbund" +size 26x16 +[ XXXXXXH] +[------------ & H] +[ H HXXXXXXX H# H|#] +[&HXH H-----H #H #H ] +[XXXHXHX @ H ## |#V] +[H--H H#V###XXX ##H ##H||#V] +[H H H# $# $ H # H#--V] +[H H# $#### XXH $H#$ $$] +[H H# &##### H #H# #] +[H # #####$ XXH||H#H###] +[H # $##### $ H # H## ] +[HV$ # ###### HXH ###H ##] +[H # #H $#$ # H H # H# $] +[H # H###### HXH # ## ##] +[H # H ] +[X#X#########XXXX#X#XXX#XXX] + +#----------------------------------------------------------------------------- +level "Level 113 (original)" +author "Broderbund" +size 26x16 +[| ] +[| ] +[###############H## $ @ ] +[ & H##V#XXXXXH] +[$ HHHHHHHHHHH H H] +[#$ H HHHHHHHH H $ $ H###H] +[ #$H H H #|# ####H] +[ #H H$ $ $ $ H # H] +[ #$ H#V#V#V# H &$$$H] +[ # H H #H##H] +[ H H H H H H ] +[ H H H& ] +[ H H H H ###H] +[ H H H H H] +[ & $|# H & H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 114 (original)" +author "Broderbund" +size 26x16 +[ -- -- - ] +[ #####$-H########H-$####$ ] +[ ######$H########H$###### ] +[ #######H########H####### ] +[ ## ####H### H### # ] +[ ## ###H###$$$ H###$$$- ] +[ ## ###H###### H######$ ] +[ ## ###H###### H ###### ] +[ ## ###H###### H ##### ] +[ ## $###H### H ## ] +[ ##$####H###$$$$$H##$$$## ] +[ #######H########H##V#### ] +[ ###### H########H #V#### ] +[ ##### H########H V### ] +[ & & H @ H & & ] +[########|###HH###|########] + +#----------------------------------------------------------------------------- +level "Level 115 (original)" +author "Broderbund" +size 26x16 +[ |] +[-------- #H $$ |] +[ $#$ H#H#X#X#X#XVX#X#X#] +[ $# #$ H#H $ $ ------] +[ $# #$H##X#X#X#X#H H] +[ # VH#XXXXXXXXXH $ H] +[ H--------H###V###H] +[ H# H] +[ $ @$ H# H] +[H#######H &$ $ H# $ $&H] +[H &$ $ H#XXX#X#X#XX#XVX#H] +[H#######H####$ ### H] +[H $ $ H###### ## H] +[H#######H####### # H] +[H $ $ H######## $ $ H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 116 (original)" +author "Broderbund" +size 26x16 +[#|#X#X#X#X#XX# #|#X ##|###] +[#|######X#XXHX X|X# # | H] +[X| #X H | $ &| H] +[##V##H------H##V#########H] +[@ $ H$H#X$ H X X#X # H] +[####H##HX#X $ X X ---H] +[ X# HX HXXX#XX# X -----#H] +[ & H H #---------X $##H] +[VX##H H$XX#$ #X$ X ## H] +[V X H $X#XX#$ X#---H# H] +[ # H $X $$$ X$ X H H] +[----H$X H#X# X$ #H#####] +[ H XX--H X $ H XXXX] +[ H#X#$$ H--H H ####H X ] +[ H$ $##$&$$H--H ##XH &$] +[###########H $H$##########] + +#----------------------------------------------------------------------------- +level "Level 117 (original)" +author "Broderbund" +size 26x16 +[ ## |] +[ $ & $ XX $& $ |] +[H############H############] +[H--------- XXH ] +[ H##H --------- ] +[ ---------HXXH$ H] +[H $ ---@ ##### $H#] +[##### #H XXXXX &$H###] +[ - # #H ##### $H#####] +[##$H# #H XXXXX $H#######] +[$##H# #H---- $H#########] +[##$H# #H XX HXXXXXXXXXXX] +[$##H#$$ #H ## H ] +[##$H###V#H XX H##########H] +[$##H & H$##$H#$ H] +[###########XX###XXXXXXXXXX] + +#----------------------------------------------------------------------------- +level "Level 118 (original)" +author "Broderbund" +size 26x16 +[--------------- ] +[ $ H& ] +[ $$$ HHH ] +[ $$$ HHH ] +[ $$ HH ] +[ $$ $$$ HH HHH -------] +[$$ $$ $$ HH HH HH & ] +[ HH HH HHHHH ] +[ & HHH HHH $$$$$ ] +[HHHH HH HHHH HH HHHHH ] +[ HH HH $$$$$ ] +[ HH @ HH HHHHH ] +[###########H##############] +[ H ] +[ H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 119 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ $ | ] +[HX## |XH] +[HX$## $ $|XH] +[H #$### & ######H] +[H # # ###$ ### $ H] +[H-- #$ # # $ ##$ XXXX H] +[H ###### ##V# ##XH] +[H$ @ #XXXH# $ H] +[HXXXX-------- H###$H] +[H X &$$$$ H ###] +[H $ X$ XXXXXXXXX H $X $] +[H##### H##XX#] +[H----H------ H ] +[ H H& ] +[ $ H #################] + +#----------------------------------------------------------------------------- +level "Level 120 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | ] +[ H | H ] +[ #####H H------------H ] +[ # $ #H H & H ] +[ # #H HXXXXXX##XX##XX] +[X#XX#X#XX#XH#-----#V### #] +[ $& $ $ H# H #-- # #] +[######V####H# H#$$#$#H#$ #] +[ ----------H# H####V#H# #] +[H& H# H$ --HHH##] +[H##########H######H $ H ] +[H @H H## HHH] +[H$#### $ ##H## $ #H#$-- H] +[H## $#####$H$#####H##$ ##H] +[##################H #####] + +#----------------------------------------------------------------------------- +level "Level 121 (original)" +author "Broderbund" +size 26x16 +[ ] +[#####H| |H#####] +[##HHH$| |$HHH##] +[H###HHH$ $HHH#V#H] +[HHH#V#HHH$& &$HHH###HHH] +[ $HHH###HHH$ $HHH#V#HHH$ ] +[ $HHH#V#HHHHHH###HHH$ ] +[ $HHH###HH###HHH$ ] +[ $HHH#HH#HHH$ ] +[ $HHH###HH###HHH$ ] +[ $HHH###HHHHHH#V#HHH$ ] +[ $HHH#V#HHH$ $HHH###HHH$ ] +[HHH###HHH$ $HHH#V#HHH] +[H#V#HHH$ $HHH###H] +[##HHH$| |$HHH##] +[#####H| @ |H#####] + +#----------------------------------------------------------------------------- +level "Level 122 (original)" +author "Broderbund" +size 26x16 +[| ] +[| & $ ] +[| XXHXXXX XXXHXXXX] +[| H #$ # H# --] +[|---H-----# #----HXH $] +[#$ H $ # # H#H- ] +[ #& H--- #H # # $ HX H] +[ # # H V H#$ H] +[@ # # H HX -H] +[XX# # # H# ----- $ H#H ] +[ #V H # $ # HXH& ] +[$H### H # # $H###H] +[#HX-------H # # #H###H] +[ H VV H H] +[ H H H] +[XXXXXX#######XXXX####XXXXX] + +#----------------------------------------------------------------------------- +level "Level 123 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ -------- -|--- ] +[ H H- H H##H ] +[ H-------&H------ H#H-#H ] +[ H H# --- H# H$ VH] +[ H HV #H H# H $#] +[ H -- H# #H - @--H---#] +[H #HH| H#$H## #H # #] +[H# #H| H#######H ### ####] +[##V##| H# #$ #H-H - &H] +[##V##| H####### H### ###H] +[# $ #| H# $# #H H#$# ###H] +[#####| H#######H H### #$#H] +[#####| H# #$ H H# # H] +[# #| H#######H H#V###V#H] +[# $ |#H #H#H # $ H] + +#----------------------------------------------------------------------------- +level "Level 124 (original)" +author "Broderbund" +size 26x16 +[| |] +[| |] +[|----H H------H# #H] +[ H-----H H# $ #H] +[ $ H H & $ H####V#H] +[###$ #HH ############V#H] +[###### H $ $ H] +[####$ H## $#$ ## H] +[#####$ H## $###$ ## H] +[######$H## $#####$ ## &$ H] +[#######H##V###########HX#H] +[# &H H #H] +[# $ ##H @ H #H] +[#######H----H####H$---H #H] +[# $ H $ H##$#H# #H$#H] +[#################H####H##H] + +#----------------------------------------------------------------------------- +level "Level 125 (original)" +author "Broderbund" +size 26x16 +[ ------ - ] +[### H-- & H#### ] +[#$ H-- #####H#### ] +[### -- V###VH#$$# ] +[ ###V V###VH#### ] +[ ###V ##-V#$$VH V###] +[ #$$V ## V###VH V###] +[ ###V H V$$#] +[ H V###] +[ V##V H ] +[V##V V$$V HV### ] +[V V V##V HV### ## ] +[V $V HV$$# ## ] +[V##V HV### ] +[ & H @ ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 126 (original)" +author "Broderbund" +size 26x16 +[ $ - - & - -&] +[H## H####$#$####H - - H] +[H $ H###########H -$ - $ H] +[H## H##$#####$##H- - - -H] +[H $ H###########H $ $ H] +[H## H#$#######$#H -- - H] +[H $ H###########H - $ -$-H] +[H## H##$#####$##H - - H] +[H $ H###########H - - H] +[H## H###$###$###H- - - -H] +[H $ H###########H $ - H] +[H## H####$#$####H -- $ H] +[H $ H###########H - - - H] +[H## H###$###$###H $ - - -H] +[H& H###########H @ ] +[H###H##$#####$##H#########] + +#----------------------------------------------------------------------------- +level "Level 127 (original)" +author "Broderbund" +size 26x16 +[ | |] +[ | & |] +[--- & |------#####H |] +[H##X### #######H$########H] +[H##$### X$ H#H## $ $ H] +[H###### XXXXXHXH ----- H] +[H ----H H H H] +[##V###H H H # H] +[--- H###### #######H####] +[$ H## ----# HHHHHH--] +[ H# XXXH #$HHHHHH $] +[H#### # XXXH #-HHHHHH -] +[H # H####H #$HHHHHH ] +[H H# H####H #-HHHHHH ] +[H@ H#H H# $#H #########H] +[############### H] + +#----------------------------------------------------------------------------- +level "Level 128 (original)" +author "Broderbund" +size 26x16 +[ - - ] +[H ###################### H] +[H # # $ $# # # H] +[H # $ ####V### # # H] +[H #V#### # $& $ # $# H] +[H # # ########### H] +[H # $ # # # # H] +[H ##### $ & # # # H] +[H # ######### # $ # H] +[H # # #$ &#V### H] +[H # $ $ # ###### # H] +[H ###V#### # # # H] +[H # $ #$ &$ #$ #$ # H] +[H ###V##########V#####V# H] +[H @ & H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 129 (original)" +author "Broderbund" +size 26x16 +[ HH ] +[ &H HH H & ] +[ ##H## ##HH## ##H## ] +[##$H$## ###HH### ##$H$##] +[# H ##$ HH $## # H ] +[##$H$ --## HH ##$H$ ] +[ ##H## ##$ HH&$ ##H## ] +[ $H$## ###HH## $H$##] +[ H # ##HH### - H #] +[##$H$## $ HH $## ##$H$##] +[ #VHV# HH ## ##HV# ] +[ H ##$ HH&$## H ] +[ ###HH### ] +[ ##HH## ] +[ @ HH ] +[############HH############] + +#----------------------------------------------------------------------------- +level "Level 130 (original)" +author "Broderbund" +size 26x16 +[H ] +[H -- ----------------] +[H | $H $ H &H] +[### ######H-------H H HXXX] +[ $ H $ H H H ] +[XXXH###& H-------H H XXXH] +[ H $ #### $ H H H] +[ @ H ####$#-------H H HXXX] +[H# H--------------H H H $ ] +[H######V##### & H XXXH] +[H$ ### #$ ####H H] +[H############XX ######H###] +[HX########### ######H##$] +[HX###########HX ##$###H###] +[HX $#########HX H ] +[H ######$ HX###########] + +#----------------------------------------------------------------------------- +level "Level 131 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ #$|$# # ] +[#---H-----#H#-----H---# ] +[ #$ H & $H$ & H $# ] +[ #-H-H---#H#---H-H-# ] +[ # H V H V H # ] +[H---# H #--H--# H #------H] +[H-H #H# #H# H-H] +[ H #H# #H# H ] +[H-H #H# @ $ #H#### H-H] +[H #H#########H#### H] +[H-H #H# ##### #H##$# H-H] +[ $H #H# ##$## #H#### H$ ] +[H-H& #H# ##### #H# &H-H] +[H---- H - - H ------ H] +[H #H# ##### #H# H] + +#----------------------------------------------------------------------------- +level "Level 132 (original)" +author "Broderbund" +size 26x16 +[| ] +[|-------------------------] +[| V###H###V ] +[| $V#V H V## $ ] +[| $V#V$$$$$H$$&$$#V# $ ] +[| ##V#V#####H######V#V# $ ] +[### H #V#V] +[# $$$$ H& $$$$ #V] +[ H######VH#######H ] +[ H H H ] +[ $H $$$$$H $ $$$$H & ] +[ HV#########HV#########H ] +[ H H H ] +[ H H H ] +[ H H @ H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 133 (original)" +author "Broderbund" +size 26x16 +[-------------H------------] +[ $ $ H $ $&$ $] +[&$ $ & $ H $ $ $ ] +[ #V##V#H H#V####H H#V# ] +[ #V##V##HH#V####VHH#V# ] +[ #V##V##VH#V####V#H#V# ] +[ #V# ##VH#V# #V#H#V# ] +[ #V# ##VH#V# #V#H#V# ] +[ #V# ##VH#V# #V#H#V# ] +[ #V# ##VH#V# #V#H#V# ] +[ #V# $##VH#V# $#V#H#V# ] +[ #V#V###VH#V#V##V#H#V##V# ] +[ #V#V### H#V#V##V H#V##V# ] +[ #V#V## H#V#V## H#V##V# ] +[ H @ H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 134 (original)" +author "Broderbund" +size 26x16 +[$& ####################] +[##H ####################] +[H###H #################] +[H######H & ##############] +[H#### ####H ###########] +[H#### #######H ########] +[H#### ##########H & #####] +[H### $ ############H ##] +[H###### $ ############H ] +[H#### #### $ ############H] +[H#### ####### $ #########H] +[H#### #########H $ ######H] +[H#### #########H### #####H] +[H$ $ $ $ #H### #####H] +[############# H### @H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 135 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | ] +[ | HXXXXXXXXXXXXXXX] +[#HH###H###H & -------] +[$#H# #H# #H############ $ ] +[ #H#$#H#$#HHHH$HHHH$HHH##H] +[VHH###H# #HHXXXXHHXXXHH $H] +[HHHHHHHHHHHHX $HHX HH##H] +[H H ## HHX -XHHX $HH# H] +[H ###H #$#HHXXXXHHXXXHH#H ] +[H #$ H ##HH---- HHHHHH#H$] +[H ## H # #H $ HHHHH###H] +[H H@## H####### $H###H] +[HHHHHHXXXXH#HHHHHX ##H###H] +[H $ XXH#H H HX ##H ##H] +[####H & #H H$HX $H# &H] + +#----------------------------------------------------------------------------- +level "Level 136 (original)" +author "Broderbund" +size 26x16 +[ &&& ] +[ $$$$$$| ] +[ $$$$$$|####### ] +[ $$$$$|XXXXXXX ] +[ |###### ] +[ || ] +[ | ] +[$$$| ] +[###H ] +[########H ] +[#############H ] +[#################H ] +[####################H ] +[######################H ] +[#######################H ] +[#######################H@ ] + +#----------------------------------------------------------------------------- +level "Level 137 (original)" +author "Broderbund" +size 26x16 +[| ] +[| $ $ $& &$ $ $ ] +[#############|############] +[ H ] +[ #H# ] +[ $H$ ] +[ & ##H## & ] +[ H $ H $ H ] +[ #H# ###H### #H# ] +[ $H$ $ H $ $H$ ] +[ ##H## ####H#### ##H##] +[ $ H $ $ H $ $ H $] +[###H### #####H##### ###H##] +[$ H $ $ H $ $ H $] +[ H H @ H ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 138 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ | ] +[ & | $-- ] +[ --------HXXX#V## H ] +[H H $ H ] +[H #####XXX###### ] +[H #$ # # # # ] +[H & $$ # # $# $$#$$# $ ] +[H####### ############## ] +[H# # ##### # ] +[H# $# $ # H$ # @ $ ] +[H##########XHX#####V##### ] +[H H --- ] +[H H H $ ] +[H $ H H ### ] +[############H $& H $ ] + +#----------------------------------------------------------------------------- +level "Level 139 (original)" +author "Broderbund" +size 26x16 +[| | X#### ] +[|##############| X $H# $ ] +[|-----------H #H--X##H# XX] +[$H#X# $ H-#H $ H# H] +[XH ## H #H X##H# $H] +[XH## $# @H #H $X& H#H-H] +[HH $########H #H X#H##H H] +[H ### XH #H H H$ ] +[H ## $XH ##H H H##] +[HH ######XH& ###H H H ] +[XH###------X#H ###HH H#H] +[#H & #XH ##H# H] +[#H#######H #XH H# H] +[#H##$####H####H###XXHH## H] +[#H#####$#H####H$ $ HH#$ H] +[#H##################H####H] + +#----------------------------------------------------------------------------- +level "Level 140 (original)" +author "Broderbund" +size 26x16 +[ ] +[ |||||||| ] +[ H######H ] +[ & H# & #H & ] +[ H# $ #H ] +[ H################H ] +[ H# # # #H ] +[ H# # # #H ] +[ H# # # #H ] +[ H# $ #& $ # $ #H ] +[H############V###########H] +[H# # # # # #H] +[H# # # # # #H] +[H# $ # $ # $ # $ # $ #H] +[H#H#H#H##H#H##H#H##H#H#H#H] +[H H#H H##H@H##H&H##H H#H H] + +#----------------------------------------------------------------------------- +level "Level 141 (original)" +author "Broderbund" +size 26x16 +[--------- ---------] +[H ######## H] +[H ############ H] +[H & ############## & H] +[H XXX################XXX H] +[H ########## H] +[H XH #### HX H] +[XXXH HXXX] +[ H $ $ $ $ $ $ H ] +[ H H ] +[ H #### H ] +[ H ###VVVV### @ H ] +[ H ###VVVVVVVVVV### H ] +[ H VVVVVVVVVVVVVV H ] +[ H VVVVVVVVVVVV H ] +[ H VVVVVVVV H ] + +#----------------------------------------------------------------------------- +level "Level 142 (original)" +author "Broderbund" +size 26x16 +[--------- ] +[ H # - - ] +[ $ $ $&H---- #### H ####] +[######### H#### H V###] +[ ----H#### H V###] +[$$ $$H # ## H V$$#] +[##$ $##H---- # ## H V###] +[###$ $### H# ## H V$$#] +[####$#### & H# ## H V###] +[#########H######$$# H V$$#] +[ H #### H V###] +[|# @ H &H V$$#] +[|##########H##########V###] +[| ###$##H#####$ ] +[| ####$#H##$ $##H $] +[|$ $##### H ############] + +#----------------------------------------------------------------------------- +level "Level 143 (original)" +author "Broderbund" +size 26x16 +[########|#################] +[@ X XXX| XH # H----- ] +[#H H XHXX XH$#HXXH ] +[$HXX#H XHXX H H $] +[##H H XH ###HXH----- ] +[$XH##X$XH##---HXH ##] +[ H XHX $X HX## $ ] +[ &H $ XHX####HX H & ] +[XX##H# XHX H--HXXXXXXXX] +[H XH# HX###### H X----] +[H# H###HX $#$ ###H X ] +[HX HXX XHX # H ] +[HX HX $XH ###########HX ] +[H ### XXHX### H ] +[H & HX$ XH $ $ H ] +[#########X##$HXX####XXXH $] + +#----------------------------------------------------------------------------- +level "Level 144 (original)" +author "Broderbund" +size 26x16 +[ ] +[ ---| --- - ] +[H H -#XXXXXX #### XXH] +[H$ H$ # X$ H] +[##H-XXH XH XX#X VVVV## HV] +[ $H &$H XH X$ H ] +[H##-HXX XHH XX#H V V H ] +[H$ H$ X HH XH #$$# H ] +[##H-XXH X HH XH ##H--H$] +[&$H $H X HHXH H #V] +[H##-HXX X HXH & H ] +[H$ H$& X XHXXXXXXXXH$] +[##H-XXH X XH# $ $ #HV] +[ $H $H X XH#H#X#X##H ] +[H##-XXX X&$$H# H#H $ $ H ] +[H @ ######XX##X#X#X#X#] + +#----------------------------------------------------------------------------- +level "Level 145 (original)" +author "Broderbund" +size 26x16 +[ & | | & ] +[ | | ] +[ | | ] +[ $###H###$ ] +[ #$#$H$#$# ] +[ $ #$H H#H H$# $ $ ] +[ ##H#H#####H H#####H#H## ] +[ $# H#H HHH H#H$# ] +[ # HH#HHHHHHHHHHHHHHH#HH #] +[ #H&$ #HHHHHH#HHHHHH# $&H#] +[ ###H #H$ H H $H# H### ] +[ $##H######H######H##$ ] +[ ## H $ H $ H ## ] +[ # H##HHHHH#HHHHH##H # ] +[ $ H###HH#HHHHH#HH###H@$ ] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 146 (original)" +author "Broderbund" +size 26x16 +[ - @ - # $ ] +[###H ########## H#### ###H] +[###H # ##### # H#### $ H] +[$##H # ##### # H##$# H###] +[###H # ##### # H#### H $ ] +[#$#H # ##### # H#$## ###H] +[###H # ##### # H#### $ H] +[$##H # ##### # H#### H###] +[###H # ##### # H ### H $ ] +[#$#H # ##### # H#### ###H] +[###H # #### # H#$## $ H] +[$##H #$#####$$# H#### H###] +[###H ########## H##$ H $ ] +[#$#H ########## H#### ###H] +[###H & & H#### & H] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 147 (original)" +author "Broderbund" +size 26x16 +[ | ] +[ & -@ | - ] +[ HH H H | H H H] +[H$H H H | H H H] +[ #HH H #$# H| H #$# H-H] +[ #H ---H&### H---H&#H# H] +[X#H#V##X##X##X##V##XH#V##H] +[# H V # $### $# #H V H] +[#-H-V--# H#----H----H-#--H] +[# H V # H# # HVH #& $ H] +[#VHX#VX##H##X##XVHX##X#V#H] +[ V## ##H## #VH## V#H] +[ H-- --#H#-- --VH#-- --#H] +[ H $ #H# $ #H $ #H] +[ $H X #H# X #H# X #H] +[#VHV#X## H ##X## H ##X#V H] + +#----------------------------------------------------------------------------- +level "Level 148 (original)" +author "Broderbund" +size 26x16 +[ && || && ] +[ $$$|##|$$$ ] +[ $$$$$|XXXXXXXXXX|$$$$$ ] +[ |###### ######| ] +[ ||| ||| ] +[ | | ] +[ | | ] +[ | | ] +[ | | ] +[ | | ] +[ | | ] +[ | | ] +[ | | ] +[ | | ] +[ | @ | ] +[#######X#####XX#####X#####] + +#----------------------------------------------------------------------------- +level "Level 149 (original)" +author "Broderbund" +size 26x16 +[ ] +[ H## ##H ] +[ H## ##H ] +[ H## ##H ] +[ H##$ & $##H ] +[ $--H################H--$&] +[H#H ##$ $## H#H] +[HH#H ## $ $ ## H#HH] +[$HH#H& #### #### H#HH$] +[ $HH#H ### ### H#HH$ ] +[ $HH#H ##$@## H#HH$ ] +[ $HH#H #### H#HH$ ] +[ $HH#H HH H#HH$ ] +[ $HH#H HH H#HH$ ] +[$ & $H##H HH H##H$ & $] +[##########################] + +#----------------------------------------------------------------------------- +level "Level 150 (original)" +author "Broderbund" +size 26x16 +[ --- &@ --- ] +[H ##H$ $H## H] +[H ##H$ $H## H] +[H ##H$ $H## H] +[H$$ ##H$ $H## $ $H] +[H###H ##H$ $H## H###H] +[H$ $H ##H$ $H## H$ $H] +[H####H ##H$ $H## H####H] +[H$&&$H ##H$ $H## H$&&$H] +[H#####H ##H$ $H## H#####H] +[H$ $H ##H$ $H## H$ $H] +[H######H ##H$$H## H######H] +[H$ $H ######## H$ $H] +[H#######H ###V## H#######H] +[H$ $H $$#V$$ H$ $H] +[############XX##|#########] + @@ -0,0 +1,602 @@ +/* $Id: lvl.c,v 1.3 2012/01/31 14:36:29 culot Exp $ */ + +/* + * Copyright (c) 2010, 2012 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> + +#include "oldrunner.h" + +struct lvlattr { + struct size siz; + char *name; + char *author; +}; + +/* Doubly-linked to store information about game levels. */ +TAILQ_HEAD(levels_head, level) levels; + +struct level { + struct lvlattr attr; + char **lay; + TAILQ_ENTRY(level) levelsp; +}; + +static struct level *curlvl; + +static enum sprite char2sprite[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* ! " # $ % & ' ( ) * + , - . / */ + 0, 0, 0, SP_BRICK, SP_MONEY, 0, SP_FOE, 0, 0, 0, 0, 0, 0, SP_ROPE, 0, 0, + +/*0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* @ A B C D E F G H I J K L M N O */ + SP_HERO, 0, 0, 0, 0, 0, 0, 0, SP_LADDER, 0, 0, 0, 0, 0, 0, 0, + +/*P Q R S T U V W X Y Z [ \ ] ^ _ */ + 0, 0, 0, 0, 0, 0, SP_FAKE_BRICK, 0, SP_CIMENT, 0, 0, 0, 0, 0, 0, 0, + +/*` a b c d e f g h i j k l m n o */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/*p q r s t u v w x y z { | } ~ */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SP_ESCAPE_LADDER, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static unsigned obj_is_static[SPRITES] = { + 1, /* SP_NONE */ + 1, /* SP_BRICK */ + 1, /* SP_BRICK_SCRACK */ + 1, /* SP_BRICK_LCRACK */ + 1, /* SP_BRICK_BROKEN */ + 1, /* SP_CIMENT */ + 1, /* SP_FAKE_BRICK */ + 1, /* SP_LADDER */ + 1, /* SP_ROPE */ + 0, /* SP_ESCAPE_LADDER */ + 0, /* SP_MONEY */ + 0, /* SP_HERO */ + 0, /* SP_FOE */ + 0, /* SP_INVALID */ +}; + +static unsigned obj_is_obstacle[SPRITES] = { + 0, /* SP_NONE */ + 1, /* SP_BRICK */ + 1, /* SP_BRICK_SCRACK */ + 1, /* SP_BRICK_LCRACK */ + 0, /* SP_BRICK_BROKEN */ + 1, /* SP_CIMENT */ + 0, /* SP_FAKE_BRICK */ + 0, /* SP_LADDER */ + 0, /* SP_ROPE */ + 0, /* SP_ESCAPE_LADDER */ + 0, /* SP_MONEY */ + 0, /* SP_HERO */ + 0, /* SP_FOE */ + 0, /* SP_INVALID */ +}; + +static void +init_layout (struct level *l) +{ + int i; + + l->lay = xcalloc (l->attr.siz.h, sizeof (char *)); + for (i = 0; i < l->attr.siz.h; i++) + l->lay[i] = xmalloc (l->attr.siz.w); +} + +static enum sprite +sprite_at_pos (const struct coord *pos) +{ + if (pos->y >= curlvl->attr.siz.h || pos->x >= curlvl->attr.siz.w) + return SP_INVALID; + + return char2sprite[(unsigned char)curlvl->lay[pos->y][pos->x]]; +} + +enum sprite +lvl_decor_at_pos (const struct coord *pos) +{ + enum sprite sp; + + sp = sprite_at_pos (pos); + return obj_is_static[sp] || (sp == SP_ESCAPE_LADDER + && money_all_collected ()) + ? sp : SP_NONE; +} + +unsigned +lvl_set_name (const char *name) +{ + if (!(curlvl->attr.name = xstrdup (name))) + return 0; + return 1; +} + +unsigned +lvl_set_author (const char *author) +{ + if (!(curlvl->attr.author = xstrdup (author))) + return 0; + return 1; +} + +/* The size must be of the form AxB. */ +unsigned +lvl_set_size (char *sizstr) +{ + const char *errstr; + char *x, *y; + int sizex, sizey; + + x = sizstr; + if (!(y = strchr (sizstr, 'x'))) + return 0; + *y++ = '\0'; + + sizex = strtonum (x, 0, LEVEL_MAX_WIDTH, &errstr); + if (errstr) + return 0; + sizey = strtonum (y, 0, LEVEL_MAX_HEIGHT, &errstr); + if (errstr) + return 0; + + curlvl->attr.siz.h = sizey; + curlvl->attr.siz.w = sizex; + + return 1; +} + +unsigned +lvl_set_row (int rownum, int rowlen, const char *row) +{ + if (rowlen != curlvl->attr.siz.w) + { + fprintf (stderr, "Incorrect row length (was: %d, expected: %d)!\n", + rowlen, curlvl->attr.siz.w); + return 0; + } + if (rownum >= curlvl->attr.siz.h) + { + fprintf (stderr, "Level row number too large (was: %d, max: %d)!\n", + rownum, curlvl->attr.siz.h); + return 0; + } + if (!curlvl->lay) + init_layout (curlvl); + + memcpy (curlvl->lay[rownum], row, rowlen); + + return 1; +} + +unsigned +lvl_width (void) +{ + return curlvl->attr.siz.w; +} + +unsigned +lvl_height (void) +{ + return curlvl->attr.siz.h; +} + +unsigned +lvl_add_new (void) +{ + struct level *lvl; + + lvl = xmalloc (sizeof *lvl); + bzero (lvl, sizeof *lvl); + lvl->attr.siz.w = LEVEL_DEFAULT_WIDTH; + lvl->attr.siz.h = LEVEL_DEFAULT_HEIGHT; + TAILQ_INSERT_TAIL (&levels, lvl, levelsp); + curlvl = lvl; + + return 1; +} + +void +lvl_init (void) +{ + TAILQ_INIT (&levels); + money_init (); + foes_init (); + bricks_init (); +} + +static void +dynaobj_free (void) +{ + money_free (); + foes_free (); + bricks_free (); +} + +static void +lvl_load_dynaobjs (void) +{ + struct coord lvlpos; + int r, c; + + dynaobj_free (); + + for (r = 0; r < curlvl->attr.siz.h; r++) + { + lvlpos.y = r; + for (c = 0; c < curlvl->attr.siz.w; c++) + { + lvlpos.x = c; + switch (sprite_at_pos (&lvlpos)) + { + case SP_HERO: + hero_set_initpos (&lvlpos); + break; + case SP_MONEY: + money_add (&lvlpos); + break; + case SP_FOE: + foes_add (&lvlpos); + break; + default: + /* DO NOTHING */ + break; + } + } + } +} + +static void +draw_hero_init_pos (void) +{ + struct coord pos; + + hero_get_initpos (&pos); + hero_set_pos (&pos); +} + +static void +draw_static_objects (void) +{ + int r; + + for (r = 0; r < curlvl->attr.siz.h; r++) + { + struct coord pos; + int c; + + pos.y = r; + for (c = 0; c < curlvl->attr.siz.w; c++) + { + enum sprite sp; + + pos.x = c; + sp = sprite_at_pos (&pos); + gfx_show_sprite (obj_is_static[sp] ? sp : SP_NONE, &pos); + } + } +} + +static void +draw_level (void) +{ + draw_static_objects (); + money_draw (); + bricks_draw (); + foes_draw (); +} + +static void +lvl_update_new (void) +{ + draw_hero_init_pos (); + draw_level (); +} + +static void +show_level_info (void) +{ + char title[BUFSIZ], info[BUFSIZ]; + + (void)snprintf (title, sizeof title, "LEVEL #%d", game_level_num ()); + (void)snprintf (info, sizeof info, + "\t Name: %s\n\n" + "\tAuthor: %s\n", + curlvl->attr.name, curlvl->attr.author); + gfx_popup (title, info); +} + +static void +load_level (void) +{ + lvl_load_dynaobjs (); + lvl_update_new (); + hero_init (); + show_level_info (); +} + +static void +lvl_select_current (int lvlnum) +{ + curlvl = TAILQ_FIRST (&levels); + while (lvlnum) + { + curlvl = TAILQ_NEXT (curlvl, levelsp); + EXIT_IF (curlvl == 0, "lvl_select_current: invalid level number"); + lvlnum--; + } +} + +/* Load the level, assign initial player position and draw it. */ +unsigned +lvl_load (int levelnum) +{ + lvl_select_current (levelnum); + load_level (); + + return 1; +} + +unsigned +lvl_load_next (void) +{ + if (!(curlvl = TAILQ_NEXT (curlvl, levelsp))) + game_won (); + game_level_inc (); + load_level (); + + return 1; +} + +unsigned +lvl_load_prev (void) +{ + struct level *previous_lvl; + + if (!(previous_lvl = TAILQ_PREV (curlvl, levels_head, levelsp))) + return 0; + + curlvl = previous_lvl; + game_level_dec (); + load_level (); + + return 1; +} + +void +lvl_won (void) +{ + lvl_load_next (); +} + +void +lvl_lost (void) +{ + load_level (); +} + +void +lvl_draw_escape_ladder (void) +{ + int r; + + for (r = 0; r < curlvl->attr.siz.h; r++) + { + struct coord pos; + int c; + + pos.y = r; + for (c = 0; c < curlvl->attr.siz.w; c++) + { + pos.x = c; + if (sprite_at_pos (&pos) == SP_ESCAPE_LADDER) + gfx_show_sprite (SP_ESCAPE_LADDER, &pos); + } + } +} + +static unsigned +valid_decor_move (const struct coord *pos_orig, const struct coord *pos_dest, + enum move wanted_move, enum sprite sp) +{ + enum sprite sp_orig, sp_dest; + + sp_orig = lvl_decor_at_pos (pos_orig); + if (wanted_move == MOV_FALL && sp_orig == SP_ROPE) + return 0; + + if (pos_dest->y < 0 && sp_orig == SP_ESCAPE_LADDER) + return 1; + + sp_dest = lvl_decor_at_pos (pos_dest); + switch (sp_dest) + { + case SP_NONE: + case SP_ROPE: + if (wanted_move == MOV_UP) + return sp_orig == SP_LADDER || sp_orig == SP_ESCAPE_LADDER ? 1 : 0; + else + return 1; + + case SP_BRICK: + return wanted_move != MOV_UP && bricks_broken_at (pos_dest) ? 1 : 0; + + case SP_CIMENT: + return 0; + + case SP_LADDER: + return wanted_move == MOV_FALL ? 0 : 1; + + case SP_ESCAPE_LADDER: + if (sp == SP_HERO) + return wanted_move == MOV_FALL ? 0 : 1; + else + return wanted_move == MOV_UP ? 0 : 1; + + default: + return 0; + /* NOTREACHED */ + } +} + +unsigned +lvl_valid_move (const struct coord *orig, enum move wanted_move, + struct coord *dest, enum sprite sp) +{ + if (wanted_move == MOV_NONE) + return 0; + + coord_compute (orig, wanted_move, dest); + if (dest->y >= (int)curlvl->attr.siz.h + || dest->x < 0 || dest->x >= curlvl->attr.siz.w) + return 0; + + return valid_decor_move (orig, dest, wanted_move, sp); +} + +unsigned +lvl_valid_dig (const struct coord *pos) +{ + switch (lvl_decor_at_pos (pos)) + { + case SP_BRICK: + return 1; + default: + return 0; + } +} + +unsigned +lvl_nothing_below (const struct coord *pos) +{ + struct coord below; + + coord_below (pos, &below); + return lvl_decor_at_pos (&below) == SP_NONE ? 1 : 0; +} + +unsigned +lvl_obstacle_at (const struct coord *pos) +{ + enum sprite sp; + + if (pos->y < 0 || pos->x < 0 + || pos->y > curlvl->attr.siz.h || pos->x > curlvl->attr.siz.w) + return 1; + + sp = char2sprite[(unsigned char)curlvl->lay[pos->y][pos->x]]; + return obj_is_obstacle[sp]; +} + +void +lvl_objects_update (void) +{ + bricks_update (); + bricks_draw (); + money_draw (); + foes_update_pos (); +} + +unsigned +lvl_got_hole_below (const struct coord *pos) +{ + struct coord below; + + coord_below (pos, &below); + if (!bricks_broken_at (&below)) + return 0; + else + { + if (foes_at_pos (&below) || hero_at_pos (&below)) + return 0; + else + return 1; + } +} + +static unsigned +got_way (const struct coord *orig, + enum move wanted_dir, enum move prefered_move) +{ + struct coord pos; + + coord_copy (orig, &pos); + while (!lvl_obstacle_at (&pos)) + { + struct coord wanted_pos; + + coord_set_yx (&wanted_pos, + pos.y + (wanted_dir == MOV_UP ? -1 : 1), pos.x); + if (valid_decor_move (&pos, &wanted_pos, wanted_dir, SP_NONE)) + return 1; + + pos.x += prefered_move == MOV_RIGHT ? 1 : -1; + } + + return 0; +} + +enum move +lvl_shortest_way (const struct coord *orig, + enum move wanted_dir, enum move prefered_move) +{ + struct coord dest; + + if (lvl_valid_move (orig, wanted_dir, &dest, SP_NONE)) + return wanted_dir; + else + { + if (got_way (orig, wanted_dir, prefered_move)) + return prefered_move; + else + return coord_opposite_dir (prefered_move); + } +} + +int +lvl_random_xpos (void) +{ + return rand () % curlvl->attr.siz.w; +} @@ -0,0 +1,96 @@ +/* $Id: mem.c,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +#include "oldrunner.h" + +void * +xmalloc (size_t size) +{ + void *p; + + EXIT_IF (size == 0, "xmalloc: zero size"); + p = malloc (size); + EXIT_IF (p == 0, "xmalloc: out of memory"); + + return p; +} + +void * +xcalloc (size_t nmemb, size_t size) +{ + void *p; + + EXIT_IF (nmemb == 0 || size == 0, "xcalloc: zero size"); + EXIT_IF (SIZE_MAX / nmemb < size, "xcalloc: overflow"); + p = calloc (nmemb, size); + EXIT_IF (p == 0, "xcalloc: out of memory"); + + return p; +} + +void * +xrealloc (void *ptr, size_t nmemb, size_t size) +{ + void *new_ptr; + size_t new_size; + + new_size = nmemb * size; + EXIT_IF (new_size == 0, "xrealloc: zero size"); + EXIT_IF (SIZE_MAX / nmemb < size, "xrealloc: overflow"); + new_ptr = realloc (ptr, new_size); + EXIT_IF (new_ptr == 0, "xrealloc: out of memory"); + + return new_ptr; +} + +char * +xstrdup (const char *str) +{ + size_t len; + char *cp; + + len = strlen (str) + 1; + cp = xmalloc (len); + + return strncpy (cp, str, len); +} + +void +xfree (void *p) +{ + EXIT_IF (p == 0, "xfree: null pointer"); + free (p); +} @@ -0,0 +1,100 @@ +/* $Id: money.c,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "oldrunner.h" + +struct money { + struct coord pos; + SLIST_ENTRY(money) moneyp; +}; + +SLIST_HEAD(, money) money_list; + +void +money_init (void) +{ + SLIST_INIT (&money_list); +} + +void +money_free (void) +{ + while (!SLIST_EMPTY (&money_list)) + { + struct money *m; + + m = SLIST_FIRST (&money_list); + SLIST_REMOVE_HEAD (&money_list, moneyp); + xfree (m); + } +} + +void +money_add (const struct coord *pos) +{ + struct money *m; + + m = xmalloc (sizeof *m); + coord_set_yx (&m->pos, pos->y, pos->x); + SLIST_INSERT_HEAD (&money_list, m, moneyp); +} + +void +money_draw (void) +{ + struct money *m; + + SLIST_FOREACH (m, &money_list, moneyp) + gfx_show_sprite (SP_MONEY, &m->pos); +} + +void +money_check_at (const struct coord *hero_pos) +{ + struct money *m; + + SLIST_FOREACH (m, &money_list, moneyp) + { + if (coord_equal (&m->pos, hero_pos)) + { + SLIST_REMOVE (&money_list, m, money, moneyp); + game_score_inc (); + return; + } + } +} + +unsigned +money_all_collected (void) +{ + return SLIST_EMPTY (&money_list); +} diff --git a/oldrunner.6 b/oldrunner.6 new file mode 100755 index 0000000..fb91ef0 --- /dev/null +++ b/oldrunner.6 @@ -0,0 +1,102 @@ +.\" $Id: oldrunner.6,v 1.2 2012/01/06 10:13:55 culot Exp $ +.\" +.\" Copyright (c) 2010, 2012 Frederic Culot <frederic@culot.org> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" - Redistributions of source code must retain the above +.\" copyright notice, this list of conditions and the +.\" following disclaimer. +.\" +.\" - Redistributions in binary form must reproduce the above +.\" copyright notice, this list of conditions and the +.\" following disclaimer in the documentation and/or other +.\" materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.fam C +.TH OLDRUNNER 6 "January 31, 2012" "OLDRUNNER(6)" "Oldrunner Manual" +.SH NAME +Oldrunner \- Broderbund's Loderunner remake +.SH SYNOPSIS +.B "oldrunner " +[\fB-v\fP] [\fB-l\fP<\fInum\fP>] +.SH DESCRIPTION +Oldrunner is a remake of Broderbund's Loderunner which contains the +150 original game levels. In order to win a level, the player '\fB@\fP' +must collect all gold bags '\fB$\fP' without being touched by ennemies +(same sprite '\fB@\fP' as player but in reverse video). Once all gold +is collected an escape ladder usually appears and the player must +travel to the top of the screen to reach the next level. The player can +dig holes into floors to temporarily trap ennemies and may then safely +walk atop them. Over time, floors dug into will regenerate, filling in +these holes. A trapped ennemy who cannot escape a hole before it fills +is consumed, immediately respawning in a random location at the top of +the level. +.SH OPTIONS +The following options are supported: +.TP +\fB-l\fP <num> +Start the game at level number \fInum\fP. +.TP +\fB-v\fP +Display oldrunner version and exit. +.SH CONFIGURATION +The game can be configured by modifying the variables found in +the cfg.h header file and recompiling. The default keys are the +following (\fB^X\fP means \fBcontrol\fP and \fBX\fP keys pressed +simultaneously): +.TP +\fBh\fP +move left +.TP +\fBl\fP +move right +.TP +\fBk\fP +move up +.TP +\fBj\fP +move down +.TP +\fBs\fP +dig on the left +.TP +\fBd\fP +dig on the right +.TP +\fB^g\fP +commit suicide +.TP +\fB^n\fP +go to next level +.TP +\fB^p\fP +go back to previous level +.TP +\fB^d\fP +quit the game +.SH SEE ALSO +ncurses(3) +.br +oldrunner web page: http://culot.org/public/Code/oldrunner.html +.SH AUTHOR +\fBFrederic Culot\fP <frederic@culot.org>. +.SH COPYRIGHT +Copyright (c) 2010, 2012 by Frederic Culot. +.br +This software is released under the BSD License. diff --git a/oldrunner.c b/oldrunner.c new file mode 100644 index 0000000..135cce0 --- /dev/null +++ b/oldrunner.c @@ -0,0 +1,86 @@ +/* $Id: oldrunner.c,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <limits.h> +#include <stdio.h> +#include <unistd.h> + +#include "oldrunner.h" + +/* + * Oldrunner is a remake of the Loadrunner game from Broderbund, and one of the + * first computer games my father offered me. I wrote this in memory of him. + * + * Jean-Francois Culot + * 1952-Sep-30 - 2009-Oct-20 + */ +int +main (int argc, char **argv) +{ + const char *errstr; + int ch, startlvl; + + startlvl = 0; + while ((ch = getopt (argc, argv, "l:v")) != -1) + { + switch (ch) + { + case 'l': + startlvl = (int)strtonum (optarg, 0, INT_MAX, &errstr) - 1; + if (errstr) + { + fprintf (stderr, "Bad level number: %s\n", errstr); + return 1; + } + break; + case 'v': + fputs ("oldrunner-" VERSION "\n", stdout); + return 0; + default: + goto err; + } + } + argc -= optind; + argv += optind; + if (argc >= 1) + { + err: + fputs ("usage: oldrunner [-v] [-l<num>]\n", stderr); + return 0; + } + + game_init (startlvl); + usr_input (); + game_end (); + + return 0; +} diff --git a/oldrunner.h b/oldrunner.h new file mode 100644 index 0000000..5e32306 --- /dev/null +++ b/oldrunner.h @@ -0,0 +1,282 @@ +/* $Id: oldrunner.h,v 1.2 2012/01/06 10:11:30 culot Exp $ */ + +/* + * Copyright (c) 2010, 2012 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OLDRUNNER_H +#define OLDRUNNER_H + +#include <stdlib.h> +#include <stdio.h> + +#include "config.h" +#include "compat.h" +#include "cfg.h" + +/* Option to set auto-center mode on/off */ +#define AUTO_CENTER_MODE 0 + +/* Game level screen properties. */ +#define LEVEL_DEFAULT_WIDTH 26 +#define LEVEL_DEFAULT_HEIGHT 16 +#define LEVEL_MAX_WIDTH 128 +#define LEVEL_MAX_HEIGHT 128 +#define VIEWPORT_WIDTH 80 +#define VIEWPORT_HEIGHT 24 + +/* Possible characters states. */ +#define STATE_ALIVE 0x01 +#define STATE_FALLING 0x02 +#define STATE_DIGGING 0x04 +#define STATE_TRAPPED 0x08 + +/* Game sprites. */ +enum sprite { + /* Sprites used to draw a level. */ + SP_NONE, + SP_BRICK, + SP_BRICK_SCRACK, + SP_BRICK_LCRACK, + SP_BRICK_BROKEN, + SP_CIMENT, + SP_FAKE_BRICK, + SP_LADDER, + SP_ROPE, + SP_ESCAPE_LADDER, + + /* Sprites used for objects. */ + SP_MONEY, + + /* Sprites used to draw characters. */ + SP_HERO, + SP_FOE, + SP_INVALID, + SPRITES +}; + +enum move { + MOV_UP, + MOV_DOWN, + MOV_LEFT, + MOV_RIGHT, + MOV_FALL, + MOV_NONE, + MOVES +}; + +struct size { + unsigned h; /* height */ + unsigned w; /* width */ +}; + +struct coord { + int y; /* Position on the vertical axis. */ + int x; /* Position on the horizontal axis. */ +}; + +struct timer { + double time; /* time in usec. */ + double elapsed; +}; + +/* Structure defining all possible user inputs. */ +struct usr_input { + int key; +}; + +struct game_info { +#define NO_CHANGE 0x0 +#define LEVEL_CHANGE 0x1 +#define SCORE_CHANGE 0x2 +#define LIVES_CHANGE 0x4 + int state; + + unsigned level; + unsigned score; + unsigned lives; +}; + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +#define __FILE_POS__ __FILE__ ":" TOSTRING(__LINE__) + +#define ERROR_MSG(...) do { \ + char msg[BUFSIZ]; \ + int len; \ + \ + len = snprintf (msg, BUFSIZ, "%s: %d: ", __FILE__, __LINE__); \ + (void)snprintf (msg + len, BUFSIZ - len, __VA_ARGS__); \ + (void)fprintf (stderr, "%s\n", msg); \ +} while (0) + +#define EXIT(...) do { \ + ERROR_MSG(__VA_ARGS__); \ + exit (1); \ +} while (0) + +#define EXIT_IF(cond, ...) do { \ + if ((cond)) \ + EXIT(__VA_ARGS__); \ +} while (0) + +/* bricks.c */ +#define BRICK_COMEBACK_TIME (OLDRUNNER_TIMEOUT * 80) +void bricks_init (void); +void bricks_free (void); +void bricks_break (const struct coord *); +void bricks_draw (void); +void bricks_update (void); +unsigned bricks_broken_at (const struct coord *); + +/* coord.c */ +void coord_copy (const struct coord *, struct coord *); +void coord_below (const struct coord *, struct coord *); +void coord_above (const struct coord *, struct coord *); +enum move coord_opposite_dir (enum move); +void coord_compute (const struct coord *, enum move, struct coord *); +void coord_set_yx (struct coord *, int, int); +unsigned coord_equal (const struct coord *, const struct coord *); +void coord_diff (const struct coord *, const struct coord *, + struct coord *); + +/* foes.c */ +void foes_init (void); +void foes_free (void); +void foes_add (const struct coord *); +void foes_draw (void); +unsigned foes_at_pos (const struct coord *); +void foes_update_pos (void); +unsigned foes_wallup_at (const struct coord *); + +/* game.c */ +void game_won (void); +void game_init (int); +void game_end (void); +void game_update (void); +unsigned game_load (const char *); +void game_score_inc (void); +int game_level_num (void); +void game_level_inc (void); +void game_level_dec (void); +void game_lives_inc (void); +void game_lives_dec (void); + +/* gfx.c */ +void gfx_init (void); +void gfx_end (void); +void gfx_alert (void); +void gfx_center_at (struct coord *); +void gfx_update (void); +void gfx_get_input (struct usr_input *); +void gfx_show_sprite (enum sprite, const struct coord *); +void gfx_move_sprite (enum sprite, const struct coord *, const struct coord *); +void gfx_update_info (const struct game_info *); +void gfx_popup (const char *, const char *); +void gfx_game_over (void); +void gfx_game_won (void); + +/* hero.c */ +void hero_init (void); +void hero_draw (void); +void hero_set_pos (const struct coord *); +void hero_set_initpos (const struct coord *); +void hero_get_pos (struct coord *); +void hero_get_initpos (struct coord *); +unsigned hero_at_pos (const struct coord *); +void hero_move (enum move); +void hero_dig (enum move); +void hero_dig_done (void); +void hero_trapped (void); +void hero_die (void); +unsigned hero_wallup_at (const struct coord *); + +/* io.c */ +FILE *io_fopen (const char *); +void io_fclose (FILE *); +char *io_getln (FILE *); + +/* lvl.c */ +void lvl_started (void); +enum sprite lvl_decor_at_pos (const struct coord *); +void lvl_init (void); +unsigned lvl_load (int); +unsigned lvl_load_next (void); +unsigned lvl_load_prev (void); +void lvl_won (void); +void lvl_lost (void); +void lvl_draw_escape_ladder (void); +unsigned lvl_set_name (const char *); +unsigned lvl_set_author (const char *); +unsigned lvl_set_size (char *); +unsigned lvl_set_row (int, int, const char *); +unsigned lvl_width (void); +unsigned lvl_height (void); +unsigned lvl_add_new (void); +unsigned lvl_valid_move (const struct coord *, enum move, struct coord *, + enum sprite); +unsigned lvl_valid_dig (const struct coord *); +unsigned lvl_nothing_below (const struct coord *); +unsigned lvl_obstacle_at (const struct coord *); +void lvl_objects_update (void); +unsigned lvl_got_hole_below (const struct coord *); +enum move lvl_shortest_way (const struct coord *, enum move, enum move); +int lvl_random_xpos (void); +enum move lvl_random_hdir (void); + +/* mem.c */ +void *xmalloc (size_t); +void *xcalloc (size_t, size_t); +void *xrealloc (void *, size_t, size_t); +char *xstrdup (const char *); +void xfree (void *); + +/* money.c */ +void money_init (void); +void money_free (void); +void money_add (const struct coord *); +void money_draw (void); +void money_check_at (const struct coord *); +unsigned money_all_collected (void); + +/* timer.c */ +void timer_get_time (struct timer *); +void timer_start (struct timer *); +void timer_stop (struct timer *); +double timer_diff (const struct timer *, const struct timer *); +double timer_elapsed (const struct timer *); +void timer_set (const struct timer *, struct timer *); +void timer_add (struct timer *, double); +unsigned timer_delay_elapsed (struct timer *, double); + +/* usr.c */ +void usr_input (void); +void usr_reset_input (void); + +#endif /* OLDRUNNER_H */ @@ -0,0 +1,95 @@ +/* $Id: timer.c,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/time.h> + +#include "oldrunner.h" + +#define SEC2USEC 1000000 + +void +timer_get_time (struct timer *now) +{ + struct timeval t; + + (void)gettimeofday (&t, 0); + now->time = (double)t.tv_sec * SEC2USEC + t.tv_usec; +} + +void +timer_start (struct timer *t) +{ + timer_get_time (t); +} + +void +timer_stop (struct timer *t) +{ + struct timer now; + + timer_get_time (&now); + t->elapsed = timer_diff (t, &now); + t->time = now.time; +} + +double +timer_diff (const struct timer *t1, const struct timer *t2) +{ + return t1->time - t2->time; +} + +double +timer_elapsed (const struct timer *t) +{ + return t->elapsed; +} + +void +timer_set (const struct timer *orig, struct timer *dest) +{ + dest->time = orig->time; +} + +void +timer_add (struct timer *t, double val) +{ + t->time += val; +} + +unsigned +timer_delay_elapsed (struct timer *t, double delay) +{ + struct timer now; + + timer_get_time (&now); + return timer_diff (&now, t) > delay ? 1 : 0; +} @@ -0,0 +1,113 @@ +/* $Id: usr.c,v 1.1.1.1 2010/07/17 17:30:32 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot <frederic@culot.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "oldrunner.h" + +#define ORKEY_NONE -1 +#define USER_DELAY OLDRUNNER_TIMEOUT + +static struct usr_input rec_input; + +void +usr_reset_input (void) +{ + rec_input.key = ORKEY_NONE; +} + +void +usr_input (void) +{ + struct timer user_timer; + + timer_get_time (&user_timer); + usr_reset_input (); + for (;;) + { + struct usr_input input; + + game_update (); + gfx_get_input (&input); + if (!timer_delay_elapsed (&user_timer, USER_DELAY)) + { + if (input.key != ORKEY_NONE) + rec_input.key = input.key; + continue; + } + + switch (rec_input.key) + { + case ORKEY_EXIT: + return; + + case ORKEY_MOVE_RIGHT: + hero_move (MOV_RIGHT); + break; + case ORKEY_MOVE_LEFT: + hero_move (MOV_LEFT); + break; + case ORKEY_MOVE_UP: + hero_move (MOV_UP); + break; + case ORKEY_MOVE_DOWN: + hero_move (MOV_DOWN); + break; + + case ORKEY_DIG_LEFT: + hero_dig (MOV_LEFT); + break; + case ORKEY_DIG_RIGHT: + hero_dig (MOV_RIGHT); + break; + + case ORKEY_LEVEL_NEXT: + lvl_load_next (); + break; + case ORKEY_LEVEL_PREV: + lvl_load_prev (); + break; + + case ORKEY_SUICIDE: + hero_die (); + break; + + default: + /* + * No action were performed by the user in the time interval. + * Simulate gravity by requiring a fall by default. + */ + hero_move (MOV_FALL); + break; + } + + timer_get_time (&user_timer); + } +} |