/* 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