scummvm/engines/glk/alan3/container.cpp

187 lines
5.8 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 "glk/alan3/container.h"
#include "glk/alan3/instance.h"
#include "glk/alan3/syserr.h"
#include "glk/alan3/inter.h"
#include "glk/alan3/lists.h"
#include "glk/alan3/memory.h"
#include "glk/alan3/current.h"
#include "glk/alan3/msg.h"
#include "glk/alan3/output.h"
namespace Glk {
namespace Alan3 {
/* PUBLIC DATA */
ContainerEntry *containers; /* Container table pointer */
/*----------------------------------------------------------------------*/
static int countInContainer(int containerIndex) { /* IN - the container to count in */
int j = 0;
for (uint instanceIndex = 1; instanceIndex <= header->instanceMax; instanceIndex++)
if (isIn(instanceIndex, containerIndex, DIRECT))
/* Then it's in this container also */
j++;
return (j);
}
/*----------------------------------------------------------------------*/
static int sumAttributeInContainer(
Aint containerIndex, /* IN - the container to sum */
Aint attributeIndex /* IN - the attribute to sum over */
) {
uint instanceIndex;
int sum = 0;
for (instanceIndex = 1; instanceIndex <= header->instanceMax; instanceIndex++)
if (isIn(instanceIndex, containerIndex, DIRECT)) { /* Then it's directly in this cont */
if (instances[instanceIndex].container != 0) /* This is also a container! */
sum = sum + sumAttributeInContainer(instanceIndex, attributeIndex);
sum = sum + getInstanceAttribute(instanceIndex, attributeIndex);
}
return (sum);
}
/*----------------------------------------------------------------------*/
static bool containerIsEmpty(int container) {
uint i;
for (i = 1; i <= header->instanceMax; i++)
if (isDescribable(i) && isIn(i, container, TRANSITIVE))
return FALSE;
return TRUE;
}
/*======================================================================*/
void describeContainer(CONTEXT, int container) {
if (!containerIsEmpty(container) && !isOpaque(container))
CALL1(list, container)
}
/*======================================================================*/
bool passesContainerLimits(CONTEXT, Aint theContainer, Aint theAddedInstance) {
LimitEntry *limit;
Aword props;
if (!isAContainer(theContainer))
syserr("Checking limits for a non-container.");
/* Find the container properties */
props = instances[theContainer].container;
if (containers[props].limits != 0) { /* Any limits at all? */
for (limit = (LimitEntry *) pointerTo(containers[props].limits); !isEndOfArray(limit); limit++)
if ((int)limit->atr == 1 - I_COUNT) { /* TODO This is actually some encoding of the attribute number, right? */
if (countInContainer(theContainer) >= (int)limit->val) {
R0CALL1(interpret, limit->stms)
return (FALSE);
}
} else {
if (sumAttributeInContainer(theContainer, limit->atr) + getInstanceAttribute(theAddedInstance, limit->atr) > limit->val) {
R0CALL1(interpret, limit->stms)
return (FALSE);
}
}
}
return (TRUE);
}
/*======================================================================*/
int containerSize(int container, ATrans trans) {
Aword i;
Aint count = 0;
for (i = 1; i <= header->instanceMax; i++) {
if (isIn(i, container, trans))
count++;
}
return (count);
}
/*======================================================================*/
void list(CONTEXT, int container) {
uint i;
Aword props;
Aword foundInstance[2] = {0, 0};
int found = 0;
Aint previousThis = current.instance;
current.instance = container;
/* Find container table entry */
props = instances[container].container;
if (props == 0) syserr("Trying to list something not a container.");
for (i = 1; i <= header->instanceMax; i++) {
if (isDescribable(i)) {
/* We can only see objects and actors directly in this container... */
if (admin[i].location == container) { /* Yes, it's in this container */
if (found == 0) {
if (containers[props].header != 0) {
CALL1(interpret, containers[props].header)
} else {
if (isAActor(containers[props].owner))
printMessageWithInstanceParameter(M_CARRIES, containers[props].owner);
else
printMessageWithInstanceParameter(M_CONTAINS, containers[props].owner);
}
foundInstance[0] = i;
} else if (found == 1)
foundInstance[1] = i;
else {
printMessageWithInstanceParameter(M_CONTAINS_COMMA, i);
}
found++;
}
}
}
if (found > 0) {
if (found > 1)
printMessageWithInstanceParameter(M_CONTAINS_AND, foundInstance[1]);
printMessageWithInstanceParameter(M_CONTAINS_END, foundInstance[0]);
} else {
if (containers[props].empty != 0) {
CALL1(interpret, containers[props].empty)
} else {
if (isAActor(containers[props].owner))
printMessageWithInstanceParameter(M_EMPTYHANDED, containers[props].owner);
else
printMessageWithInstanceParameter(M_EMPTY, containers[props].owner);
}
}
needSpace = TRUE;
current.instance = previousThis;
}
} // End of namespace Alan3
} // End of namespace Glk