/*
* 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);
}