From 2b3b9dc4649727851004b8223b6af38b57c0c790 Mon Sep 17 00:00:00 2001 From: culot Date: Fri, 27 Jul 2018 11:22:11 +0200 Subject: oldrunner initial import --- ChangeLog | 20 + GNUmakefile | 65 ++ README | 21 + TODO | 13 + bricks.c | 169 +++ cfg.h | 61 + compat.h | 56 + compat/fgetln.c | 86 ++ compat/queue.h | 527 +++++++++ compat/strtonum.c | 65 ++ configure | 78 ++ coord.c | 117 ++ foes.c | 290 +++++ game.c | 297 +++++ gfx.c | 448 ++++++++ hero.c | 188 +++ io.c | 86 ++ levels/original.lvl | 3155 +++++++++++++++++++++++++++++++++++++++++++++++++++ lvl.c | 602 ++++++++++ mem.c | 96 ++ money.c | 100 ++ oldrunner.6 | 102 ++ oldrunner.c | 86 ++ oldrunner.h | 282 +++++ timer.c | 95 ++ usr.c | 113 ++ 26 files changed, 7218 insertions(+) create mode 100644 ChangeLog create mode 100644 GNUmakefile create mode 100644 README create mode 100644 TODO create mode 100644 bricks.c create mode 100644 cfg.h create mode 100644 compat.h create mode 100644 compat/fgetln.c create mode 100644 compat/queue.h create mode 100644 compat/strtonum.c create mode 100755 configure create mode 100644 coord.c create mode 100644 foes.c create mode 100644 game.c create mode 100644 gfx.c create mode 100644 hero.c create mode 100644 io.c create mode 100644 levels/original.lvl create mode 100644 lvl.c create mode 100644 mem.c create mode 100644 money.c create mode 100755 oldrunner.6 create mode 100644 oldrunner.c create mode 100644 oldrunner.h create mode 100644 timer.c create mode 100644 usr.c 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 + + * 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 + + * 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 + + * first public release + +2010-04-01 Frederic Culot + + * 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 diff --git a/README b/README new file mode 100644 index 0000000..0f5c066 --- /dev/null +++ b/README @@ -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. + + diff --git a/TODO b/TODO new file mode 100644 index 0000000..ce71a4c --- /dev/null +++ b/TODO @@ -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 + * 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); + } + } + } +} diff --git a/cfg.h b/cfg.h new file mode 100644 index 0000000..79d64a1 --- /dev/null +++ b/cfg.h @@ -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 + * 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 + * 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 +#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 + +#include +#include +#include +#include + + +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 +#include +#include + +#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 +# +# 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 <>$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 <>$CONFIG_H +#define HAVE_CURSES_H +#define HAVE_BZERO +#define HAVE_FGETLN +#define HAVE_QUEUE_H +#define HAVE_STRTONUM +EOF + cat <>$CONFIG_MK +LIBS+= -lcurses +EOF + ;; +# ------------------------------------------------------------------------------ + Linux) + cat <>$CONFIG_H +#define HAVE_NCURSES_H +#define HAVE_BZERO +EOF + cat <>$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 diff --git a/coord.c b/coord.c new file mode 100644 index 0000000..e07c45f --- /dev/null +++ b/coord.c @@ -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 + * 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; +} diff --git a/foes.c b/foes.c new file mode 100644 index 0000000..abe3fba --- /dev/null +++ b/foes.c @@ -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 + * 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; +} diff --git a/game.c b/game.c new file mode 100644 index 0000000..0cb27f9 --- /dev/null +++ b/game.c @@ -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 + * 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 +#include +#include + +#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--; +} diff --git a/gfx.c b/gfx.c new file mode 100644 index 0000000..45c9522 --- /dev/null +++ b/gfx.c @@ -0,0 +1,448 @@ +/* $Id: gfx.c,v 1.2 2012/01/31 14:53:07 culot Exp $ */ + +/* + * Copyright (c) 2010 Frederic Culot + * 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 + +#include "oldrunner.h" + +#ifdef HAVE_CURSES_H +# include +#elif defined HAVE_NCURSES_H +# include +#elif defined HAVE_NCURSES_NCURSES_H +# include +#elif defined HAVE_NCURSESW_NCURSES_H +# include +#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 (); +} diff --git a/hero.c b/hero.c new file mode 100644 index 0000000..040ec9b --- /dev/null +++ b/hero.c @@ -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 + * 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; +} diff --git a/io.c b/io.c new file mode 100644 index 0000000..171155a --- /dev/null +++ b/io.c @@ -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 + * 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 +#include +#include + +#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##|#########] + diff --git a/lvl.c b/lvl.c new file mode 100644 index 0000000..addea43 --- /dev/null +++ b/lvl.c @@ -0,0 +1,602 @@ +/* $Id: lvl.c,v 1.3 2012/01/31 14:36:29 culot Exp $ */ + +/* + * Copyright (c) 2010, 2012 Frederic Culot + * 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 + +#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; +} diff --git a/mem.c b/mem.c new file mode 100644 index 0000000..1d4c471 --- /dev/null +++ b/mem.c @@ -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 + * 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 +#include +#include + +#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); +} diff --git a/money.c b/money.c new file mode 100644 index 0000000..91688cd --- /dev/null +++ b/money.c @@ -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 + * 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 +.\" 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 +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 . +.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 + * 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 +#include +#include + +#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]\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 + * 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 +#include + +#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 */ diff --git a/timer.c b/timer.c new file mode 100644 index 0000000..b78c560 --- /dev/null +++ b/timer.c @@ -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 + * 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 + +#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; +} diff --git a/usr.c b/usr.c new file mode 100644 index 0000000..af359ac --- /dev/null +++ b/usr.c @@ -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 + * 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); + } +} -- cgit v1.2.3