Sign in with
Sign up | Sign in
Your question

greenhorn makes progress

Last response: in Video Games
Share
Anonymous
June 9, 2005 8:04:31 PM

Archived from groups: rec.games.roguelike.development (More info?)

Hey, it's me again. Well I sort of made some progress. First off, the
good news is that I can generate a random map of rooms and connected
hallways. the problem is it doesn't quite work out as nicely as it
should. For some reason the second time I ran the program I got 1 room
with 1 hallway coming out of it.
I was wondering if there was anyone willing to take a glance at my
atrociously written code to see if there are any glaring flaws that
might cause this problem.

synopsis of what the code does:
1: fill map with rock "#"
2: grab a random spot and carve a room (making sure that there is no
existing room/hallway in the way and we don't cross the border.)
3: start at a wall of the room and tunnel a hallway. (same conditions
as step 2)
4: at the end of the hall either carve a room or turn and make a new
hallway.
(note that in steps 3 and 4 we keep trying randome sides/directions
until we succeed or our trial counter reaches 1000.)

It's not all that complex, but I thaut it would do the trick well
enough to get started.

Thank you in advance to which ever brave soul volunteers. You will be
doing me an enormus favor and erning my eternal gratitude.

Almost forgot, for anyone who missed my previous post, I am coding in
C.
And if you e-mail me please put R.L.proj at the start of the
subjectline so I know what it's about and don't chunk it.

Yet again thank you in advance.
Anonymous
June 9, 2005 11:35:19 PM

Archived from groups: rec.games.roguelike.development (More info?)

aerospace1028@hotmail.com wrote:
> Hey, it's me again. Well I sort of made some progress. First off, the
> good news is that I can generate a random map of rooms and connected
> hallways. the problem is it doesn't quite work out as nicely as it
> should. For some reason the second time I ran the program I got 1 room
> with 1 hallway coming out of it.
> I was wondering if there was anyone willing to take a glance at my
> atrociously written code to see if there are any glaring flaws that
> might cause this problem.
>
> synopsis of what the code does:
> 1: fill map with rock "#"
> 2: grab a random spot and carve a room (making sure that there is no
> existing room/hallway in the way and we don't cross the border.)
> 3: start at a wall of the room and tunnel a hallway. (same conditions
> as step 2)
> 4: at the end of the hall either carve a room or turn and make a new
> hallway.
> (note that in steps 3 and 4 we keep trying randome sides/directions
> until we succeed or our trial counter reaches 1000.)
>
> It's not all that complex, but I thaut it would do the trick well
> enough to get started.
>
> Thank you in advance to which ever brave soul volunteers. You will be
> doing me an enormus favor and erning my eternal gratitude.
>
> Almost forgot, for anyone who missed my previous post, I am coding in
> C.
> And if you e-mail me please put R.L.proj at the start of the
> subjectline so I know what it's about and don't chunk it.
>
> Yet again thank you in advance.

If the relevant code is short enough (which I suspect it is), go ahead
and post it here. Getting a group analysis is likely to lead to
better results than just sending it to a few volunteers.

So, anyways, just post it here. I'm positive it'll come well under
the limit.


--
My projects are currently on hold, but I do have
some junk at the site below.

http://www.freewebs.com/timsrl/index.htm

--
Anonymous
June 10, 2005 11:42:38 AM

Archived from groups: rec.games.roguelike.development (More info?)

Timothy Pruett wrote:
<snip>
If the relevant code is short enough (which I suspect it is), go ahead
> and post it here. Getting a group analysis is likely to lead to
> better results than just sending it to a few volunteers.
>
> So, anyways, just post it here. I'm positive it'll come well under
> the limit.
Alright. Here it is:

/* map header file. */
/* header file for map generation stuff */

/* definitions */
#define MaxLevel 4 //maximum levels in the dungeon
#define ScreenWidth 70 // width of the screen
#define ScreenHeight 20 // height of the screen

/* function declarations */
void MakeLvl(void);
void ShowMap(void);
int CheckRoom(posint, posint, posint, posint, posint);
void DigRoom(posint, posint, posint, posint, posint);
int CheckHall(posint, posint, posint);
void DigHall(posint, posint, posint, posint);
void BuildMap(void);
int FrameRoom(posint, posint, posint, posint);
int AddHall(posint, posint, posint, posint, posint);

/* enumerators for dungeon features */
enum feature{rock, room, hall, up, down};
/* end map header */

/* map.c */
/* main file for building a map */
#include "proj.h" //all necessary definitions and stuff

/* our map array */
int map[ScreenWidth][ScreenHeight];

void MakeLvl(void)
{
int i, j;
for (i = 0; i < ScreenWidth; i++)
{
for (j = 0; j < ScreenHeight; j++)
{
map[j] = rock;
}
}
}

void ShowMap(void)
{
int i, j;
for (j = (ScreenHeight-1); j >= 0; j--)
{
for (i = 0; i < ScreenWidth; i++)
{
switch(map[j])
{
case rock:
putch('#');
break;
case room:
case hall:
putch('.');
break;
case up:
putch('<');
break;
case down:
putch('>');
break;
}
}
printf("\n");
}
}

int CheckRoom(posint XStart, posint YStart, posint XLength, posint
YLength, posint Quad)
{
int i, j, valid;
posint trial = 0;
switch(Quad)
{
case 1:
/* we want to expand up and to the right. Into the first quadrant */
for (i = XStart; i < (XStart+XLength); i++)
{
for (j = YStart; j < (YStart+YLength); j++)
{
if ((map[j] != rock) || (((i >= ScreenWidth-1) || (i <= 0)) || ((j
>= ScreenHeight-1) || (j <= 0))))
{
/* either we hit the edge or we run over an existing feature. return
failure */
return -1;
}
}
}
/* now check to satisfy the boarder */
valid = FrameRoom(XStart, YStart, XLength, YLength);
if (valid != 0)
{
/* we can't build here. */
return -1;
}
break;
case 2:
/* we want to expand up and to the left. Into the 2nd quadrant */
for (i = (XStart-XLength); i < XStart; i--)
{
for (j = YStart; j < (YStart+YLength); j++)
{
if ((map[j] != rock) || (((i >= ScreenWidth-1) || (i <= 0)) || ((j
>= ScreenHeight-1) || (j <= 0))))
{
/* either we hit the edge or we run over an existing feature. return
failure */
return -1;
}
}
}
/* now check that we can frame it */
valid = FrameRoom((XStart-(XLength-1)), YStart, XLength, YLength);
if (valid != 0)
{
/* we can't build here. */
return -1;
}
break;
case 3:
/* we want to expand down and to the left. Into the third quadrant */
for (i = (XStart-XLength); i < XStart; i--)
{
for (j = (YStart-YLength); j < YStart; j--)
{
if ((map[j] != rock) || (((i >= ScreenWidth-1) || (i <= 0)) || ((j
>= ScreenHeight-1) || (j <= 0))))
{
/* either we hit the edge or we run over an existing feature. return
failure */
return -1;
}
}
}
/* now check if we can frame the area. */
valid = FrameRoom((XStart-(XLength-1)), (YStart-(YLength-1)), XLength,
YLength);
if (valid != 0)
{
/* we can't build here. */
return -1;
}
break;
case 4:
/* we want to expand down and to the right, into the fourth quadrant.
*/
for (i = XStart; i < (XStart+XLength); i++)
{
for (j = (YStart-YLength); j < YStart; j--)
{
if ((map[j] != rock) || (((i >= ScreenWidth-1) || (i <= 0)) || ((j
>= ScreenHeight-1) || (j <= 0))))
{
/* either we hit the edge or we run over an existing feature. return
failure */
return -1;
}
}
}
/* check for the frame */
valid = FrameRoom(XStart, (YStart-(YLength-1)), XLength, YLength);
if (valid != 0)
{
return -1;
}
break;
default:
/* some sort of programmer error. */
system("cls");
printf("\n\n\t error constructing a room!!! ");
printf("\n\n\t NOW TERMINATING!!!");
return -1;
break;
}
/* we must have been successful */
DigRoom(XStart, YStart, XLength, YLength, Quad);
/* now build a hallway. */
do
{
switch(Quad)
{
case 1:
valid = AddHall(XStart, YStart, XLength, YLength, dice(1, 4));
break;
case 2:
valid = AddHall((XStart-(XLength-1)), YStart, XLength, YLength, dice(1,
4));
break;
case 3:
valid = AddHall((XStart-(XLength-1)), (YStart-(YLength-1)), XLength,
YLength, dice(1, 4));
break;
case 4:
valid = AddHall(XStart, (YStart-(YLength-1)), XLength, YLength, dice(1,
4));
break;
default:
/* some sort of programmer error. */
clrscr();
printf("\n\n\t\t ANN ERROR OCCURED CALLING ADDHALL FROM CHECK
ROOM!!!");
printf("\n\n\t\tNOW TERMINATING!!!");
return -1;
break;
}
if (valid != 0)
{
trial += 1;
}
else
{
trial += 100000;
}
}
while ((valid != 0) && (trial < 100));
return 0;
}

void DigRoom(posint XStart, posint YStart, posint XLength, posint
YLength, posint Quad)
{
posint i, j;
switch(Quad)
{
case 1:
/* we want to expand up and to the right. Into the first quadrant */
for (i = XStart; i < (XStart+XLength); i++)
{
for (j = YStart; j < (YStart+YLength); j++)
{
map[j] = room;
}
}
break;
case 2:
/* we want to expand up and to the left. Into the 2nd quadrant */
for (i = (XStart-XLength); i < XStart; i--)
{
for (j = YStart; j < (YStart+YLength); j++)
{
map[j] = room;
}
}
break;
case 3:
/* we want to expand down and to the left. Into the third quadrant */
for (i = (XStart-XLength); i < XStart; i--)
{
for (j = (YStart-YLength); j < YStart; j--)
{
map[j] = room;
}
}
break;
case 4:
/* we want to expand down and to the right, into the fourth quadrant.
*/
for (i = XStart; i < (XStart+XLength); i++)
{
for (j = (YStart-YLength); j < YStart; j--)
{
map[j] = room;
}
}
break;
}
}

int CheckHall(posint XStart, posint YStart, posint Aim)
{
posint i, j, hallLength, valid;
posintL trial;
i = XStart;
j = YStart;
if ((map[j] != rock) || (((i >= ScreenWidth-1) || (i <= 0)) || ((j
>= ScreenHeight-1) || (j <= 0))))
{
return -1;
}
hallLength = 1;
valid = 1;
while (valid == 1)
{
switch(Aim)
{
case 1:
/* we want to go to the right. */
i++;
/* check the boarders */
if ((map[j-1] != rock) || (map[j+1] != rock))
{
valid = 0;
}
break;
case 2:
/* we want to go up */
j++;
/* check the boarders */
if ((map[i-1][j] != rock) || (map[i+1][j] != rock))
{
valid = 0;
}
break;
case 3:
/* we want to go to the left */
i--;
/* check the edges */
if ((map[j-1] != rock) || (map[j+1] != rock))
{
valid = 0;
}
break;
case 4:
/* we want to go down */
j--;
if ((map[i-1][j] != rock) || (map[i+1][j] != rock))
{
valid = 0;
}
break;
default:
/* some sort of programmer error. */
system("cls");
printf("\n\n\t\t FAILURE CHECKING CORRIDOR!!!");
printf("\n\n\t\t NOW TERMINATING!!!");
valid = 0;
break;
}
if ((map[j] != rock) || (((i >= ScreenWidth-1) || (i <= 0)) || ((j
>= ScreenHeight-1) || (j <= 0))))
{
/* we either hit an existing structure or left the edge of the map. */
valid = 0;
}
else
{
hallLength++;
}
}
/* success */
hallLength = dice(1, hallLength);
DigHall(XStart, YStart, hallLength, Aim);
/* now put something off the end of our hall. */
do
{
switch(Aim)
{
case 1:
/* we went to the right. */
switch(dice(1, 3))
{
case 1:
/* build under the last square. */
switch(dice(1, 2))
{
case 1:
/* build another hall. */
valid = CheckHall((XStart+hallLength), (YStart-1), dice(1, 4));
break;
case 2:
/* build a room */
valid = CheckRoom((XStart+hallLength), (YStart-1), dice(3, 2), dice(3,
2), dice(1, 4));
break;
default:
valid = -1;
}
break;
case 2:
/* build off the end of the hall */
switch(dice(1, 2))
{
case 1:
/* build another hall. */
valid = CheckHall((XStart+(hallLength+1)), YStart, dice(1, 4));
break;
case 2:
/* build a room */
valid = CheckRoom((XStart+(hallLength+1)), YStart, dice(3, 2), dice(3,
2), dice(1, 4));
break;
default:
valid = -1;
}
break;
case 3:
/*build off of the top of the end square. */
switch(dice(1, 2))
{
case 1:
/* build another hall. */
valid = CheckHall((XStart+hallLength), (YStart+1), dice(1, 2));
break;
case 2:
/* build a room */
valid = CheckRoom((XStart+hallLength), (YStart+1), dice(3, 2), dice(3,
2), dice(1, 4));
break;
default:
valid = -1;
}
break;
default:
valid = -1;
break;
}
break;
case 2:
/* we built up. */
switch(dice(1, 3))
{
case 1:
/* build to the right of the top square. */
switch(dice(1, 2))
{
case 1:
/* build a hallway. */
valid = CheckHall((XStart+1), (YStart+hallLength), dice(1, 2));
break;
case 2:
/* build a room */
valid = CheckRoom((XStart+1), (YStart+hallLength), dice(3, 2), dice(3,
2), dice(1, 4));
break;
default:
valid = -1;
break;
}
break;
case 2:
/* build off the top of the end square. */
switch(dice(1, 2))
{
case 1:
/* build a hallway. */
valid = CheckHall(XStart, (YStart+(hallLength+1)), dice(1, 3));
break;
case 2:
/* build a room */
valid = CheckRoom(XStart, (YStart+(hallLength+1)), dice(3, 2), dice(3,
2), dice(1, 2));
break;
default:
valid = -1;
break;
}
break;
case 3:
/* build to the left of the top square. */
switch(dice(1, 2))
{
case 1:
/* build a hallway. */
valid = CheckHall((XStart-1), (YStart+hallLength), (dice(1, 2))+1);
break;
case 2:
/* build a room */
valid = CheckRoom((XStart-1), (YStart+hallLength), dice(3, 2), dice(3,
2), dice(1, 2));
break;
default:
valid = -1;
break;
}
break;
default:
valid = -1;
break;
}
break;
case 3:
/* we built to the left */
switch(dice(1, 3))
{
case 1:
/* build above the end square. */
switch(dice(1, 2))
{
case 1:
valid = CheckHall((XStart-(hallLength-1)), (YStart+1), (dice(1, 2))+1);
break;
case 2:
valid = CheckRoom((XStart-(hallLength-1)), (YStart+1), dice(3, 2),
dice(3, 2), (dice(1, 2))+1);
break;
default:
valid = -1;
}
case 2:
/* build off of the end square. */
switch(dice(1, 2))
{
case 1:
valid = CheckHall((XStart-hallLength), YStart, (dice(1, 3))+1);
break;
case 2:
valid = CheckRoom((XStart-hallLength), YStart, dice(13, 2), dice(3, 2),
(dice(1, 2))+1);
break;
default:
valid = -1;
}
break;
case 3:
/* build under the end square. */
switch(dice(1, 2))
{
case 1:
valid = CheckHall((XStart-(hallLength-1)), (YStart-1), (dice(1, 2))+1);
break;
case 2:
valid = CheckRoom((XStart-(hallLength-1)), (YStart-1), dice(3, 2),
dice(3, 2), (dice(1, 2))+1);
break;
default:
valid = -1;
break;
}
default:
valid = -1;
break;
}
break;
case 4:
/* we built down */
switch(dice(1, 3))
{
case 1:
/* build to the left of the end square */
switch(dice(1, 2))
{
case 1:
valid = CheckHall((XStart-1), (YStart-hallLength), ((dice(1, 2))+2));
break;
case 2:
valid = CheckRoom((XStart-1), (YStart-hallLength), dice(3, 2), dice(3,
2), dice(1, 4));
break;
default:
valid = -1;
break;
}
break;
case 2:
/* build below the end square. */
switch(dice(1, 2))
{
case 1:
valid = CheckHall(XStart, (YStart-hallLength), dice(1, 4));
break;
case 2:
valid = CheckRoom(XStart, (YStart-hallLength), dice(3, 2), dice(3, 2),
((dice(1, 2))+2));
break;
default:
valid = -1;
break;
}
break;
case 3:
/*build to the right of the end square. */
switch(dice(1, 2))
{
case 1:
valid = CheckHall((XStart+1), (YStart-(hallLength-1)), dice(1, 4));
break;
case 2:
valid = CheckRoom((XStart+1), (YStart-(hallLength-1)), dice(3, 2),
dice(3, 2), dice(1, 4));
break;
default:
valid = -1;
break;
}
default:
valid = -1;
break;
}
break;
default:
valid = -1;
break;
}
if (valid != 0)
{
trial += 1;
}
else
{
trial += 100000000;
}
}
while ((valid != 0) && (trial < 100000));

return 0;
}

void DigHall(posint XStart, posint YStart, posint HallLength, posint
Aim)
{
posint i;
switch(Aim)
{
case 1:
/* we want to go to the right. */
for (i = XStart; i < (XStart+HallLength); i++)
{
map[YStart] = hall;
}
break;
case 2:
/* we want to go up */
for (i = YStart; i < (YStart+HallLength); i++)
{
map[XStart] = hall;
}
break;
case 3:
/* we want to go to the left */
for (i = XStart; i > (XStart-HallLength); i--)
{
map[YStart] = hall;
}
break;
case 4:
/* we want to go down */
for (i = YStart; i > (YStart-HallLength); i--)
{
map[XStart] = hall;
}
break;
}
}

void BuildMap(void)
{
int valid;
posint trial = 0;
/* start by filling the level with just rock */
MakeLvl();
/* then carve out the first room */
do
{
valid = CheckRoom(dice(1, (ScreenWidth-1)), dice(1, (ScreenHeight-1)),
dice(3, 2), dice(3, 2), dice(1, 4));
if (valid != 0)
{
trial++;
}
}
while ((valid != 0) && (trial < 100));
}

int FrameRoom(posint XStart, posint YStart, posint XLength, posint
YLength)
{
int i, j, hallCount;
/* first check the four corners. They must either be rock or a hall
way. */
/* lower left corner */
if ((map[(XStart-1)][YStart] == room) || (map[(XStart-1)][(YStart-1)]
== room) || (map[XStart][(YStart-1)] == room))
{
return -1;
}
else if (map[(XStart-1)][(YStart-1)] == hall)
{
if ((map[(XStart-1)][YStart] == hall) && (map[XStart][(YStart-1)] ==
hall))
{
return -1;
}
else if ((map[(XStart-1)][YStart] != hall) && (map[XStart][(YStart-1)]
!= hall))
{
return -1;
}
}

/* check the upper left corner */
if ((map[(XStart-1)][(YStart+(YLength-1))] == room) ||
(map[(XStart-1)][(YStart+YLength)] == room) ||
(map[XStart][(YStart+YLength)] == room))
{
return -1;
}
else if (map[(XStart-1)][(YStart+YLength)] == hall)
{
if ((map[(XStart-1)][(YStart+(YLength-1))] == hall) &&
(map[XStart][(YStart+YLength)] == hall))
{
/* all three corner positions are hall. */
return -1;
}
else if ((map[(XStart-1)][(YStart+(YLength-1))] != hall) &&
(map[XStart][(YStart+YLength)] != hall))
{
/* an isolated hall on a diagonal. */
return -1;
}
}

/* check the upper left corner */
if ((map[(XStart+(XLength-1))][(YStart+YLength)] == room) ||
(map[(XStart+XLength)][(YStart+YLength)] == room) ||
(map[(XStart+XLength)][(YStart+(YLength-1))] == room))
{
return -1;
}
else if (map[(XStart+XLength)][(YStart+YLength)] == hall)
{
if ((map[(XStart+(XLength-1))][(YStart+YLength)] == hall) &&
(map[(XStart+XLength)][(YStart+(YLength-1))] == room))
{
return -1;
}
else if ((map[(XStart+(XLength-1))][(YStart+YLength)] != room) &&
(map[(XStart+XLength)][(YStart+(YLength-1))] != room))
{
return -1;
}
}

/* chekc lower right corner. */
if ((map[(XStart+XLength)][YStart] == room) ||
(map[(XStart+XLength)][(YStart-1)] == room) ||
(map[(XStart+(XLength-1))][(YStart-1)] == room))
{
return -1;
}
else if (map[(XStart+XLength)][(YStart-1)] == hall)
{
if ((map[(XStart+XLength)][YStart] == hall) &&
(map[(XStart+(XLength-1))][(YStart-1)] == hall))
{
return -1;
}
else if ((map[(XStart+XLength)][YStart] != hall) &&
(map[(XStart+(XLength-1))][(YStart-1)] != hall))
{
return -1;
}
}

/* check the left most wall */
hallCount = 0;
for (j = YStart; j < (YStart+YLength); j++)
{
if (map[(XStart-1)][j] != rock)
{
if (map[(XStart-1)][j] == hall)
{
/* we hit a hallway */
hallCount++;
}
else
{
/* we hit another room or something */
return -1;
}
}
}
if (((YLength <= 4) && (hallCount > 1)) || (hallCount > 2))
{
return -1;
}
hallCount = 0;
/* check the top of the room */
for (i = XStart; i < (XStart+XLength); i++)
{
if (map[(YStart+YLength)] != rock)
{
if (map[(YStart+YLength)] == hall)
{
hallCount++;
}
else
{
return -1;
}
}
}
if (((YLength <= 4) && (hallCount > 1)) || (hallCount >2))
{
return -1;
}
hallCount = 0;
/* check right side */
for (j = YStart; j < (YStart+YLength); j++)
{
if (map[(XStart+XLength)][j] != rock)
{
if (map[(XStart+XLength)][j] == hall)
{
hallCount++;
}
else
{
return -1;
}
}
}
if (((YLength <= 4) && (hallCount > 1)) || (hallCount > 2))
{
return -1;
}
hallCount = 0;
/* check bottom */
for (i = XStart; i < (XStart+XLength); i++)
{
if (map[(YStart-1)] != rock)
{
if (map[(YStart-1)] == hall)
{
hallCount++;
}
else
{
return -1;
}
}
}
if (((YLength <= 4) && (hallCount > 1)) || (hallCount >2))
{
return -1;
}
return 0;
}

int AddHall(posint XStart, posint YStart, posint XLength, posint
YLength, posint side)
{
int valid;
/* go to that side */
switch(side)
{
case 1:
/* the right wall. */
valid = CheckHall((XStart+XLength), (YStart+(dice(1, YLength)-1)),
dice(1, 4));
break;
case 2:
/* the top wall. */
valid = CheckHall((XStart+(dice(1, XLength)-1)), (YStart+YLength),
dice(1, 4));
break;
case 3:
/* the left wall. */
valid = CheckHall((XStart-1), (YStart+(dice(1, YLength)-1)), dice(1,
4));
break;
case 4:
/* the bottom wall. */
valid = CheckHall((XStart+(dice(1, XLength)-1)), (YStart-1), dice(1,
4));
break;
default:
/* some sort of programmer error. */
clrscr();
printf("\n\n\t\t ERROR ADDING A NEW HALLWAY!!!");
printf("\n\n\t\tNOW TERMINATING!!!\n\n");
return -1;
break;
}
return valid;
}
/* end map.c*/

/* dice rollar function from other file */
posint dice(posint diceNum, posint diceSide)
{
posint count, total;
total = 0;
for (count = 1; count <= diceNum; count++)
{
total += ((rand()%diceSide)+1);
}
if (total < diceNum)
{
return diceNum;
}
else if (total > diceNum*diceSide)
{
return diceNum*diceSide;
}
else
{
return total;
}
}
Related resources
Anonymous
June 16, 2005 7:55:44 PM

Archived from groups: rec.games.roguelike.development (More info?)

aerospace1028@hotmail.com napisał(a):
[...]

I read somewhere that, when possible, it is better to use "++i" than
"i++", because it's faster. If you care for speed.

--
Milesss
m i l e s s s @ i n t e r i a . p l
www.milesss.mylog.pl
"/0"
Anonymous
June 17, 2005 4:20:03 AM

Archived from groups: rec.games.roguelike.development (More info?)

"Milesss" <milesssREMOVE@interia.pl> wrote in message
news:D 8s0bc$thf$1@news.interia.pl...
> aerospace1028@hotmail.com napisal(a):
> [...]
>
> I read somewhere that, when possible, it is better to use "++i" than
> "i++", because it's faster. If you care for speed.
>

OTOH, if you care about the actual reason you could always read the C
ng FAQ.

--
Glen
L:p yt E+++ T-- R+ P+++ D+ G+ F:*band !RL RLA-
W:AF Q+++ AI++ GFX++ SFX-- RN++++ PO--- !Hp Re-- S+
!