diff options
Diffstat (limited to 'ksokoban/Map.cpp')
-rw-r--r-- | ksokoban/Map.cpp | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/ksokoban/Map.cpp b/ksokoban/Map.cpp new file mode 100644 index 00000000..7dbb1cfa --- /dev/null +++ b/ksokoban/Map.cpp @@ -0,0 +1,204 @@ +/* + * ksokoban - a Sokoban game for KDE + * Copyright (C) 1998 Anders Widell <d95-awi@nada.kth.se> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <stdio.h> + +#include "Map.h" + +Map::Map() : xpos_(-1), ypos_(-1), width_(0), height_(0), objectsLeft_(-1) { +} + + +void +Map::map (int x, int y, int val) { + assert (x>=0 && x<=MAX_X && y>=0 && y<=MAX_Y); + if ((map (x, y) & (OBJECT | GOAL)) == OBJECT) objectsLeft_--; + if ((val & (OBJECT | GOAL)) == OBJECT) objectsLeft_++; + currentMap_[y+1][x+1] = val; + + if (val != 0) { + if (width_ <= x) width_ = x+1; + if (height_ <= y) height_ = y+1; + } +} + +void +Map::setMap (int x, int y, int bits) { + assert ((map (x, y) & bits) == 0); + if (goal (x, y) && ((bits & OBJECT) == OBJECT)) objectsLeft_--; + assert (objectsLeft_ >= 0); + currentMap_[y+1][x+1] |= bits; + + if (bits != 0) { + if (width_ <= x) width_ = x+1; + if (height_ <= y) height_ = y+1; + } +} + +void +Map::clearMap (int x, int y, int bits) { + assert ((map (x, y) & bits) == bits); + if (goal (x, y) && ((bits & OBJECT) == OBJECT)) objectsLeft_++; + currentMap_[y+1][x+1] &= ~bits; +} + +void +Map::clearMap () { + memset (currentMap_, 0, (MAX_Y+3)*(MAX_X+3)*sizeof (char)); + objectsLeft_ = 0; + width_ = height_ = 0; +} + +bool +Map::fillFloor (int x, int y) { + if (badCoords (x, y)) return false; + if ((currentMap_[y+1][x+1] & (WALL|FLOOR)) != 0) return true; + + currentMap_[y+1][x+1] |= FLOOR; + bool a = fillFloor (x, y-1); + bool b = fillFloor (x, y+1); + bool c = fillFloor (x-1, y); + bool d = fillFloor (x+1, y); + + return a && b && c && d; +} + +bool +Map::step (int _x, int _y) { + assert (!badCoords (xpos_, ypos_)); + assert (empty (xpos_, ypos_)); + + int xd=0, yd=0; + if (_x < xpos_) xd = -1; + if (_x > xpos_) xd = 1; + if (_y < ypos_) yd = -1; + if (_y > ypos_) yd = 1; + if (badDelta (xd, yd) || badCoords (_x, _y)) return false; + + int x=xpos_, y=ypos_; + do { + x += xd; + y += yd; + if (!empty (x, y)) return false; + } while (!(x==_x && y==_y)); + + xpos_ = _x; + ypos_ = _y; + + return true; +} + +bool +Map::push (int _x, int _y) { + assert (!badCoords (xpos_, ypos_)); + assert (empty (xpos_, ypos_)); + + int xd=0, yd=0; + if (_x < xpos_) xd = -1; + if (_x > xpos_) xd = 1; + if (_y < ypos_) yd = -1; + if (_y > ypos_) yd = 1; + if (badDelta (xd, yd) || badCoords (_x+xd, _y+yd)) return false; + + int x=xpos_+xd, y=ypos_+yd; + if (!object (x, y)) return false; + if (!empty (_x+xd, _y+yd)) return false; + + while (!(x==_x && y==_y)) { + x += xd; + y += yd; + if (!empty (x, y)) return false; + } + + clearMap (xpos_+xd, ypos_+yd, OBJECT); + setMap (_x+xd, _y+yd, OBJECT); + + xpos_ = _x; + ypos_ = _y; + + return true; +} + +bool +Map::unstep (int _x, int _y) { + return Map::step (_x, _y); +} + +bool +Map::unpush (int _x, int _y) { + assert (!badCoords (xpos_, ypos_)); + assert (empty (xpos_, ypos_)); + + int xd=0, yd=0; + if (_x < xpos_) xd = -1; + if (_x > xpos_) xd = 1; + if (_y < ypos_) yd = -1; + if (_y > ypos_) yd = 1; + if (badDelta (xd, yd) || badCoords (_x+xd, _y+yd)) return false; + + int x=xpos_, y=ypos_; + if (!object (x-xd, y-yd)) return false; + + do { + x += xd; + y += yd; + if (!empty (x, y)) return false; + } while (!(x==_x && y==_y)); + + clearMap (xpos_-xd, ypos_-yd, OBJECT); + setMap (_x-xd, _y-yd, OBJECT); + + xpos_ = _x; + ypos_ = _y; + + return true; +} + +void +Map::printMap(void) { + for (int y=0; y<height_; y++) { + for (int x=0; x<width_; x++) { + switch (map (x, y) & ~FLOOR) { + case WALL: + printf("#"); + break; + case GOAL: + printf("%c", x==xpos_ && y==ypos_ ? '+' : '.'); + break; + case OBJECT: + printf("$"); + break; + case OBJECT|GOAL: + printf("*"); + break; + case 0: + printf("%c", x==xpos_ && y==ypos_ ? '@' : ' '); + break; + default: + printf("<%X>", map(x,y)&FLOOR); + break; + } + } + printf ("\n"); + } +} + |