/* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team * Copyright (©) Crossfire Development Team (restored, original file without copyright notice) * * Deliantra is free software: you can redistribute it and/or modify it under * the terms of the Affero GNU General Public License as published by the * Free Software Foundation, either version 3 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 Affero GNU General Public License * and the GNU General Public License along with this program. If not, see * . * * The authors can be reached via e-mail to */ /* * Expands a layout by 2x in each dimension. * H. S. Teoh * -------------------------------------------------------------------------- * $Id: expand2x.C,v 1.11 2010/07/02 03:40:14 root dead $ * * ALGORITHM * * ... (TBW) */ #include "global.h" #include "random_map.h" #include "rproto.h" /* Copy the old tile X into the new one at location (i*2, j*2) and * fill up the rest of the 2x2 result with \0: * X ---> X \0 * \0 \0 */ static void expand_misc (Layout &newlayout, int i, int j, Layout &layout) { newlayout[i * 2][j * 2] = layout[i][j]; /* (Note: no need to reset rest of 2x2 area to \0 because calloc does that * for us.) */ } /* Returns a bitmap that represents which squares on the right and bottom * edges of a square (i,j) match the given character: * 1 match on (i+1, j) * 2 match on (i, j+1) * 4 match on (i+1, j+1) * and the possible combinations thereof. */ static int calc_pattern (char ch, Layout &layout, int i, int j) { int pattern = 0; if (i + 1 < layout.w && layout[i + 1][j] == ch) pattern |= 1; if (j + 1 < layout.h) { if (layout[i][j + 1] == ch) pattern |= 2; if (i + 1 < layout.w && layout[i + 1][j + 1] == ch) pattern |= 4; } return pattern; } /* Expand a wall. This function will try to sensibly connect the resulting * wall to adjacent wall squares, so that the result won't have disconnected * walls. */ static void expand_wall (Layout &newlayout, int i, int j, Layout &layout) { int wall_pattern = calc_pattern ('#', layout, i, j); int door_pattern = calc_pattern ('D', layout, i, j); int both_pattern = wall_pattern | door_pattern; newlayout[i * 2][j * 2] = '#'; if (i + 1 < layout.w) { if (both_pattern & 1) { /* join walls/doors to the right */ /* newlayout[i*2+1][j*2] = '#'; */ newlayout[i * 2 + 1][j * 2] = layout[i + 1][j]; } } if (j + 1 < layout.h) { if (both_pattern & 2) { /* join walls/doors to the bottom */ /* newlayout[i*2][j*2+1] = '#'; */ newlayout[i * 2][j * 2 + 1] = layout[i][j + 1]; } if (wall_pattern == 7) { /* if orig layout is a 2x2 wall block, * we fill the result with walls. */ newlayout[i * 2 + 1][j * 2 + 1] = '#'; } } } /* This function will try to sensibly connect doors so that they meet up with * adjacent walls. Note that it will also presumptuously delete (ignore) doors * that it doesn't know how to correctly expand. */ static void expand_door (Layout &newlayout, int i, int j, Layout &layout) { int wall_pattern = calc_pattern ('#', layout, i, j); int door_pattern = calc_pattern ('D', layout, i, j); int join_pattern; /* Doors "like" to connect to walls more than other doors. If there is * a wall and another door, this door will connect to the wall and * disconnect from the other door. */ if (wall_pattern & 3) join_pattern = wall_pattern; else join_pattern = door_pattern; newlayout[i * 2][j * 2] = 'D'; if (i + 1 < layout.w) if (join_pattern & 1) /* there is a door/wall to the right */ newlayout[i * 2 + 1][j * 2] = 'D'; if (j + 1 < layout.h) if (join_pattern & 2) /* there is a door/wall below */ newlayout[i * 2][j * 2 + 1] = 'D'; } void expand2x (Layout &layout) { Layout new_layout (layout.w * 2 - 1, layout.h * 2 - 1); new_layout.clear (); for (int i = 0; i < layout.w; i++) for (int j = 0; j < layout.h; j++) switch (layout[i][j]) { case '#': expand_wall (new_layout, i, j, layout); break; case 'D': expand_door (new_layout, i, j, layout); break; default: expand_misc (new_layout, i, j, layout); break; } layout.swap (new_layout); }