mirror of
https://github.com/softdorothy/GliderPRO.git
synced 2024-11-22 05:31:29 +00:00
7a70d18ba6
Sources for Glider PRO, a Macintosh game written by John Calhoun and published by Casady & Greene, Inc. I believe it was using CodeWarrior IDE to create a fat (68K and PowerPC) binary.
1 line
28 KiB
C
Executable File
1 line
28 KiB
C
Executable File
|
|
//============================================================================
|
|
//----------------------------------------------------------------------------
|
|
// HouseLegal.c
|
|
//----------------------------------------------------------------------------
|
|
//============================================================================
|
|
|
|
|
|
#include <NumberFormatting.h>
|
|
#include <StringCompare.h>
|
|
#include "Externs.h"
|
|
#include "ObjectEdit.h"
|
|
#include "RectUtils.h"
|
|
|
|
|
|
void WrapBannerAndTrailer (void);
|
|
void ValidateNumberOfRooms (void);
|
|
void CheckDuplicateFloorSuite (void);
|
|
void CompressHouse (void);
|
|
void LopOffExtraRooms (void);
|
|
void ValidateRoomNumbers (void);
|
|
void CountUntitledRooms (void);
|
|
void CheckRoomNameLength (void);
|
|
void MakeSureNumObjectsJives (void);
|
|
void KeepAllObjectsLegal (void);
|
|
void CheckForStaircasePairs (void);
|
|
|
|
|
|
short houseErrors, wasRoom;
|
|
Boolean isHouseChecks;
|
|
|
|
extern short numberRooms;
|
|
|
|
|
|
//============================================================== Functions
|
|
//-------------------------------------------------------------- KeepObjectLegal
|
|
|
|
// Does a test of the current object active for any illegal boundsÉ
|
|
// or values. It corrects the erros and returns true if any changesÉ
|
|
// were made.
|
|
|
|
Boolean KeepObjectLegal (void)
|
|
{
|
|
objectType *theObject;
|
|
Rect bounds, roomRect;
|
|
short direction, dist;
|
|
char wasState;
|
|
Boolean unchanged;
|
|
|
|
unchanged = true;
|
|
#ifndef COMPILEDEMO
|
|
|
|
theObject = &thisRoom->objects[objActive];
|
|
|
|
if (objActive == kInitialGliderSelected)
|
|
{
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
if ((*thisHouse)->initial.h < 0)
|
|
(*thisHouse)->initial.h = 0;
|
|
if ((*thisHouse)->initial.v < 0)
|
|
(*thisHouse)->initial.v = 0;
|
|
if ((*thisHouse)->initial.h > (kRoomWide - kGliderWide))
|
|
(*thisHouse)->initial.h = kRoomWide - kGliderWide;
|
|
if ((*thisHouse)->initial.v > (kTileHigh - kGliderHigh))
|
|
(*thisHouse)->initial.v = kTileHigh - kGliderHigh;
|
|
HSetState((Handle)thisHouse, wasState);
|
|
return (true);
|
|
}
|
|
|
|
QSetRect(&roomRect, 0, 0, kRoomWide, kTileHigh);
|
|
|
|
switch (theObject->what)
|
|
{
|
|
case kFloorVent:
|
|
case kCeilingVent:
|
|
case kFloorBlower:
|
|
case kCeilingBlower:
|
|
case kSewerGrate:
|
|
case kLeftFan:
|
|
case kRightFan:
|
|
case kTaper:
|
|
case kCandle:
|
|
case kStubby:
|
|
case kTiki:
|
|
case kBBQ:
|
|
case kInvisBlower:
|
|
case kGrecoVent:
|
|
case kSewerBlower:
|
|
case kLiftArea:
|
|
GetObjectRect(&thisRoom->objects[objActive], &bounds);
|
|
if (ForceRectInRect(&bounds, &roomRect))
|
|
{
|
|
theObject->data.a.topLeft.h = bounds.left;
|
|
theObject->data.a.topLeft.v = bounds.top;
|
|
unchanged = false;
|
|
if (theObject->what == kLiftArea)
|
|
{
|
|
theObject->data.a.distance = RectWide(&bounds);
|
|
theObject->data.a.tall = RectTall(&bounds) / 2;
|
|
}
|
|
}
|
|
if ((theObject->what == kStubby) && (theObject->data.a.topLeft.h % 2 == 0))
|
|
{
|
|
theObject->data.a.topLeft.h--;
|
|
unchanged = false;
|
|
}
|
|
if (((theObject->what == kTaper) || (theObject->what == kCandle) ||
|
|
(theObject->what == kTiki) || (theObject->what == kBBQ)) &&
|
|
(theObject->data.a.topLeft.h % 2 != 0))
|
|
{
|
|
theObject->data.a.topLeft.h--;
|
|
unchanged = false;
|
|
}
|
|
if ((theObject->what == kFloorVent) && (theObject->data.a.topLeft.v != kFloorVentTop))
|
|
{
|
|
theObject->data.a.topLeft.v = kFloorVentTop;
|
|
theObject->data.a.distance += 2;
|
|
}
|
|
if ((theObject->what == kFloorBlower) &&
|
|
(theObject->data.a.topLeft.v != kFloorBlowerTop))
|
|
{
|
|
theObject->data.a.topLeft.v = kFloorBlowerTop;
|
|
theObject->data.a.distance += 2;
|
|
}
|
|
if ((theObject->what == kSewerGrate) &&
|
|
(theObject->data.a.topLeft.v != kSewerGrateTop))
|
|
{
|
|
theObject->data.a.topLeft.v = kSewerGrateTop;
|
|
theObject->data.a.distance += 2;
|
|
}
|
|
if ((theObject->what == kFloorTrans) &&
|
|
(theObject->data.a.topLeft.v != kFloorTransTop))
|
|
{
|
|
theObject->data.a.topLeft.v = kFloorTransTop;
|
|
theObject->data.a.distance += 2;
|
|
}
|
|
if (ObjectHasHandle(&direction, &dist))
|
|
{
|
|
switch (direction)
|
|
{
|
|
case kAbove:
|
|
dist = bounds.top - dist;
|
|
if ((theObject->what == kFloorVent) ||
|
|
(theObject->what == kFloorBlower) ||
|
|
(theObject->what == kTaper) ||
|
|
(theObject->what == kCandle) ||
|
|
(theObject->what == kStubby))
|
|
{
|
|
if (dist < 36)
|
|
{
|
|
theObject->data.a.distance += dist - 36;
|
|
unchanged = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dist < 0)
|
|
{
|
|
theObject->data.a.distance += dist;
|
|
unchanged = false;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kToRight:
|
|
dist = bounds.right + dist;
|
|
if (dist > kRoomWide)
|
|
{
|
|
theObject->data.a.distance += (kRoomWide - dist);
|
|
unchanged = false;
|
|
}
|
|
break;
|
|
|
|
case kBelow:
|
|
dist = bounds.bottom + dist;
|
|
if (dist > kTileHigh)
|
|
{
|
|
theObject->data.a.distance += (kTileHigh - dist);
|
|
unchanged = false;
|
|
}
|
|
break;
|
|
|
|
case kToLeft:
|
|
dist = bounds.left - dist;
|
|
if (dist < 0)
|
|
{
|
|
theObject->data.a.distance += dist;
|
|
unchanged = false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kTable:
|
|
case kShelf:
|
|
case kCabinet:
|
|
case kFilingCabinet:
|
|
case kWasteBasket:
|
|
case kMilkCrate:
|
|
case kCounter:
|
|
case kDresser:
|
|
case kDeckTable:
|
|
case kStool:
|
|
case kTrunk:
|
|
case kInvisObstacle:
|
|
case kManhole:
|
|
case kBooks:
|
|
case kInvisBounce:
|
|
GetObjectRect(&thisRoom->objects[objActive], &bounds);
|
|
if (ForceRectInRect(&bounds, &roomRect))
|
|
{
|
|
theObject->data.b.bounds = bounds;
|
|
unchanged = false;
|
|
}
|
|
if ((theObject->what == kManhole) &&
|
|
(((bounds.left - 3) % 64) != 0))
|
|
{
|
|
theObject->data.b.bounds.left =
|
|
(((bounds.left + 29) / 64) * 64) + 3;
|
|
theObject->data.b.bounds.right =
|
|
theObject->data.b.bounds.left +
|
|
RectWide(&srcRects[kManhole]);
|
|
unchanged = false;
|
|
}
|
|
break;
|
|
|
|
case kRedClock:
|
|
case kBlueClock:
|
|
case kYellowClock:
|
|
case kCuckoo:
|
|
case kPaper:
|
|
case kBattery:
|
|
case kBands:
|
|
case kGreaseRt:
|
|
case kGreaseLf:
|
|
case kFoil:
|
|
case kInvisBonus:
|
|
case kStar:
|
|
case kSparkle:
|
|
case kHelium:
|
|
case kSlider:
|
|
GetObjectRect(&thisRoom->objects[objActive], &bounds);
|
|
if (ForceRectInRect(&bounds, &roomRect))
|
|
{
|
|
theObject->data.c.topLeft.h = bounds.left;
|
|
theObject->data.c.topLeft.v = bounds.top;
|
|
unchanged = false;
|
|
}
|
|
if ((theObject->what == kGreaseRt) &&
|
|
(bounds.right + theObject->data.c.length > kRoomWide))
|
|
{
|
|
theObject->data.c.length = kRoomWide - bounds.right;
|
|
unchanged = false;
|
|
}
|
|
else if ((theObject->what == kGreaseLf) &&
|
|
(bounds.left - theObject->data.c.length < 0))
|
|
{
|
|
theObject->data.c.length = bounds.left;
|
|
unchanged = false;
|
|
}
|
|
else if ((theObject->what == kSlider) &&
|
|
(bounds.left + theObject->data.c.length > kRoomWide))
|
|
{
|
|
theObject->data.c.length = kRoomWide - bounds.left;
|
|
unchanged = false;
|
|
}
|
|
if (theObject->data.c.topLeft.h % 2 != 0)
|
|
{
|
|
theObject->data.c.topLeft.h--;
|
|
unchanged = false;
|
|
}
|
|
if ((theObject->what != kStar) &&
|
|
(theObject->data.c.length % 2 != 0))
|
|
{
|
|
theObject->data.c.length--;
|
|
unchanged = false;
|
|
}
|
|
break;
|
|
|
|
case kUpStairs:
|
|
case kDownStairs:
|
|
case kMailboxLf:
|
|
case kMailboxRt:
|
|
case kFloorTrans:
|
|
case kCeilingTrans:
|
|
case kDoorInLf:
|
|
case kDoorInRt:
|
|
case kDoorExRt:
|
|
case kDoorExLf:
|
|
case kWindowInLf:
|
|
case kWindowInRt:
|
|
case kWindowExRt:
|
|
case kWindowExLf:
|
|
case kInvisTrans:
|
|
case kDeluxeTrans:
|
|
GetObjectRect(&thisRoom->objects[objActive], &bounds);
|
|
if (ForceRectInRect(&bounds, &roomRect))
|
|
{
|
|
theObject->data.d.topLeft.h = bounds.left;
|
|
theObject->data.d.topLeft.v = bounds.top;
|
|
unchanged = false;
|
|
if (theObject->what == kDeluxeTrans)
|
|
{
|
|
theObject->data.d.tall = ((RectWide(&bounds) / 4) << 8) +
|
|
(RectTall(&bounds) / 4);
|
|
}
|
|
}
|
|
if ((theObject->what == kDoorInLf) ||
|
|
(theObject->what == kDoorInRt))
|
|
{
|
|
if (theObject->data.d.topLeft.h +
|
|
HalfRectWide(&srcRects[kDoorInLf]) > (kRoomWide / 2))
|
|
{
|
|
theObject->data.d.topLeft.h = kDoorInRtLeft;
|
|
theObject->what = kDoorInRt;
|
|
}
|
|
else
|
|
{
|
|
theObject->data.d.topLeft.h = kDoorInLfLeft;
|
|
theObject->what = kDoorInLf;
|
|
}
|
|
}
|
|
if ((theObject->what == kDoorExRt) ||
|
|
(theObject->what == kDoorExLf))
|
|
{
|
|
if (theObject->data.d.topLeft.h +
|
|
HalfRectWide(&srcRects[kDoorExRt]) > (kRoomWide / 2))
|
|
{
|
|
theObject->data.d.topLeft.h = kDoorExRtLeft;
|
|
theObject->what = kDoorExRt;
|
|
}
|
|
else
|
|
{
|
|
theObject->data.d.topLeft.h = kDoorExLfLeft;
|
|
theObject->what = kDoorExLf;
|
|
}
|
|
}
|
|
if ((theObject->what == kWindowInLf) ||
|
|
(theObject->what == kWindowInRt))
|
|
{
|
|
if (theObject->data.d.topLeft.h +
|
|
HalfRectWide(&srcRects[kWindowInLf]) > (kRoomWide / 2))
|
|
{
|
|
theObject->data.d.topLeft.h = kWindowInRtLeft;
|
|
theObject->what = kWindowInRt;
|
|
}
|
|
else
|
|
{
|
|
theObject->data.d.topLeft.h = kWindowInLfLeft;
|
|
theObject->what = kWindowInLf;
|
|
}
|
|
}
|
|
if ((theObject->what == kWindowExRt) ||
|
|
(theObject->what == kWindowExLf))
|
|
{
|
|
if (theObject->data.d.topLeft.h +
|
|
HalfRectWide(&srcRects[kWindowExRt]) > (kRoomWide / 2))
|
|
{
|
|
theObject->data.d.topLeft.h = kWindowExRtLeft;
|
|
theObject->what = kWindowExRt;
|
|
}
|
|
else
|
|
{
|
|
theObject->data.d.topLeft.h = kWindowExLfLeft;
|
|
theObject->what = kWindowExLf;
|
|
}
|
|
}
|
|
|
|
if ((theObject->what == kInvisTrans) &&
|
|
((theObject->data.d.topLeft.v +
|
|
theObject->data.d.tall) > kTileHigh))
|
|
{
|
|
theObject->data.d.tall = kTileHigh -
|
|
theObject->data.d.topLeft.v;
|
|
unchanged = false;
|
|
}
|
|
if ((theObject->what == kInvisTrans) &&
|
|
(theObject->data.d.wide < 0))
|
|
{
|
|
theObject->data.d.wide = 0;
|
|
unchanged = false;
|
|
}
|
|
break;
|
|
|
|
case kLightSwitch:
|
|
case kMachineSwitch:
|
|
case kThermostat:
|
|
case kPowerSwitch:
|
|
case kKnifeSwitch:
|
|
case kInvisSwitch:
|
|
case kTrigger:
|
|
case kLgTrigger:
|
|
case kSoundTrigger:
|
|
GetObjectRect(&thisRoom->objects[objActive], &bounds);
|
|
if (ForceRectInRect(&bounds, &roomRect))
|
|
{
|
|
theObject->data.e.topLeft.h = bounds.left;
|
|
theObject->data.e.topLeft.v = bounds.top;
|
|
unchanged = false;
|
|
}
|
|
if (theObject->data.e.topLeft.h % 2 != 0)
|
|
{
|
|
theObject->data.e.topLeft.h--;
|
|
unchanged = false;
|
|
}
|
|
break;
|
|
|
|
case kCeilingLight:
|
|
case kLightBulb:
|
|
case kTableLamp:
|
|
case kHipLamp:
|
|
case kDecoLamp:
|
|
case kFlourescent:
|
|
case kTrackLight:
|
|
case kInvisLight:
|
|
GetObjectRect(&thisRoom->objects[objActive], &bounds);
|
|
if (ForceRectInRect(&bounds, &roomRect))
|
|
{
|
|
if ((theObject->what == kFlourescent) || (theObject->what == kTrackLight))
|
|
{
|
|
if (theObject->data.f.topLeft.h < bounds.left)
|
|
theObject->data.f.topLeft.h = bounds.left;
|
|
|
|
if (theObject->data.f.topLeft.v < bounds.top)
|
|
theObject->data.f.topLeft.v = bounds.top;
|
|
|
|
if ((theObject->data.f.topLeft.h + theObject->data.f.length) > bounds.right)
|
|
theObject->data.f.length = bounds.right - theObject->data.f.topLeft.h;
|
|
}
|
|
else
|
|
{
|
|
theObject->data.f.topLeft.h = bounds.left;
|
|
theObject->data.f.topLeft.v = bounds.top;
|
|
}
|
|
unchanged = false;
|
|
}
|
|
if (((theObject->what == kFlourescent) ||
|
|
(theObject->what == kTrackLight)) &&
|
|
((bounds.right > kRoomWide) || (bounds.left < 0)))
|
|
{
|
|
if (theObject->data.f.topLeft.h < 0)
|
|
{
|
|
theObject->data.f.topLeft.h = 0;
|
|
unchanged = false;
|
|
}
|
|
if (bounds.left < 0)
|
|
{
|
|
bounds.left = 0;
|
|
unchanged = false;
|
|
}
|
|
if (theObject->data.f.topLeft.h > kRoomWide)
|
|
{
|
|
theObject->data.f.topLeft.h = kRoomWide;
|
|
unchanged = false;
|
|
}
|
|
if (bounds.right > kRoomWide)
|
|
{
|
|
bounds.right = kRoomWide;
|
|
unchanged = false;
|
|
}
|
|
theObject->data.f.length = kRoomWide - bounds.left;
|
|
}
|
|
break;
|
|
|
|
case kShredder:
|
|
case kToaster:
|
|
case kMacPlus:
|
|
case kGuitar:
|
|
case kTV:
|
|
case kCoffee:
|
|
case kOutlet:
|
|
case kVCR:
|
|
case kStereo:
|
|
case kMicrowave:
|
|
case kCinderBlock:
|
|
case kFlowerBox:
|
|
case kCDs:
|
|
case kCustomPict:
|
|
GetObjectRect(&thisRoom->objects[objActive], &bounds);
|
|
if (ForceRectInRect(&bounds, &roomRect))
|
|
{
|
|
theObject->data.g.topLeft.h = bounds.left;
|
|
theObject->data.g.topLeft.v = bounds.top;
|
|
unchanged = false;
|
|
}
|
|
if ((theObject->what == kToaster) &&
|
|
(bounds.top - theObject->data.g.height < 0))
|
|
{
|
|
theObject->data.g.height = bounds.top;
|
|
unchanged = false;
|
|
}
|
|
if ((theObject->what == kTV) &&
|
|
(theObject->data.g.topLeft.h % 2 == 0))
|
|
{
|
|
theObject->data.g.topLeft.h--;
|
|
unchanged = false;
|
|
}
|
|
if (((theObject->what == kToaster) ||
|
|
(theObject->what == kMacPlus) ||
|
|
(theObject->what == kCoffee) ||
|
|
(theObject->what == kOutlet) ||
|
|
(theObject->what == kVCR) ||
|
|
(theObject->what == kStereo) ||
|
|
(theObject->what == kMicrowave)) &&
|
|
(theObject->data.g.topLeft.h % 2 != 0))
|
|
{
|
|
theObject->data.g.topLeft.h--;
|
|
unchanged = false;
|
|
}
|
|
break;
|
|
|
|
case kBalloon:
|
|
case kCopterLf:
|
|
case kCopterRt:
|
|
case kDartLf:
|
|
case kDartRt:
|
|
case kBall:
|
|
case kDrip:
|
|
case kFish:
|
|
case kCobweb:
|
|
GetObjectRect(&thisRoom->objects[objActive], &bounds);
|
|
if (ForceRectInRect(&bounds, &roomRect))
|
|
{
|
|
theObject->data.h.topLeft.h = bounds.left;
|
|
theObject->data.h.topLeft.v = bounds.top;
|
|
unchanged = false;
|
|
}
|
|
if (((theObject->what == kBall) ||
|
|
(theObject->what == kFish)) &&
|
|
(bounds.top - theObject->data.h.length < 0))
|
|
{
|
|
theObject->data.h.length = bounds.top;
|
|
unchanged = false;
|
|
}
|
|
if ((theObject->what == kDrip) &&
|
|
(bounds.bottom + theObject->data.h.length > kTileHigh))
|
|
{
|
|
theObject->data.h.length = kTileHigh - bounds.bottom;
|
|
unchanged = false;
|
|
}
|
|
if (((theObject->what == kBalloon) ||
|
|
(theObject->what == kCopterLf) ||
|
|
(theObject->what == kCopterRt) ||
|
|
(theObject->what == kBall) ||
|
|
(theObject->what == kDrip) ||
|
|
(theObject->what == kFish)) &&
|
|
(theObject->data.h.topLeft.h % 2 != 0))
|
|
{
|
|
theObject->data.h.topLeft.h--;
|
|
unchanged = false;
|
|
}
|
|
break;
|
|
|
|
case kOzma:
|
|
case kMirror:
|
|
case kMousehole:
|
|
case kFireplace:
|
|
case kFlower:
|
|
case kWallWindow:
|
|
case kBear:
|
|
case kCalendar:
|
|
case kVase1:
|
|
case kVase2:
|
|
case kBulletin:
|
|
case kCloud:
|
|
case kFaucet:
|
|
case kRug:
|
|
case kChimes:
|
|
GetObjectRect(&thisRoom->objects[objActive], &bounds);
|
|
if (ForceRectInRect(&bounds, &roomRect))
|
|
{
|
|
theObject->data.i.bounds = bounds;
|
|
unchanged = false;
|
|
}
|
|
if (theObject->what == kMirror)
|
|
{
|
|
if (theObject->data.i.bounds.left % 2 != 0)
|
|
{
|
|
theObject->data.i.bounds.left--;
|
|
unchanged = false;
|
|
}
|
|
if (theObject->data.i.bounds.right % 2 != 0)
|
|
{
|
|
theObject->data.i.bounds.right--;
|
|
unchanged = false;
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return (unchanged);
|
|
}
|
|
|
|
//-------------------------------------------------------------- WrapBannerAndTrailer
|
|
|
|
// Tries to wrap around the text of the banner and trailer messages.
|
|
|
|
#ifndef COMPILEDEMO
|
|
void WrapBannerAndTrailer (void)
|
|
{
|
|
char wasState;
|
|
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
|
|
WrapText((*thisHouse)->banner, 40);
|
|
WrapText((*thisHouse)->trailer, 64);
|
|
|
|
HSetState((Handle)thisHouse, wasState);
|
|
}
|
|
|
|
//-------------------------------------------------------------- ValidateNumberOfRooms
|
|
|
|
// Makes sure the number of room count and actual number of rooms match.
|
|
|
|
void ValidateNumberOfRooms (void)
|
|
{
|
|
long countedRooms, reportsRooms;
|
|
char wasState;
|
|
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
|
|
reportsRooms = (long)(*thisHouse)->nRooms;
|
|
countedRooms = (GetHandleSize((Handle)thisHouse) -
|
|
sizeof(houseType)) / sizeof(roomType);
|
|
if (reportsRooms != countedRooms)
|
|
{
|
|
(*thisHouse)->nRooms = (short)countedRooms;
|
|
numberRooms = (*thisHouse)->nRooms;
|
|
houseErrors++;
|
|
}
|
|
|
|
HSetState((Handle)thisHouse, wasState);
|
|
}
|
|
|
|
//-------------------------------------------------------------- CheckDuplicateFloorSuite
|
|
|
|
// Error check, looks for rooms with the same floor suite (stacked).
|
|
|
|
void CheckDuplicateFloorSuite (void)
|
|
{
|
|
#define kRoomsTimesSuites 8192
|
|
short i, numRooms, bitPlace;
|
|
char *pidgeonHoles;
|
|
char wasState;
|
|
|
|
pidgeonHoles = (char *)NewPtrClear(sizeof(char) * kRoomsTimesSuites);
|
|
if (pidgeonHoles == nil)
|
|
return;
|
|
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
|
|
numRooms = (*thisHouse)->nRooms;
|
|
for (i = 0; i < numRooms; i++)
|
|
{
|
|
if ((*thisHouse)->rooms[i].suite != kRoomIsEmpty)
|
|
{
|
|
bitPlace = (((*thisHouse)->rooms[i].floor + 7) * 128) +
|
|
(*thisHouse)->rooms[i].suite;
|
|
if ((bitPlace < 0) || (bitPlace >= 8192))
|
|
DebugStr("\pBlew array");
|
|
if (pidgeonHoles[bitPlace] != 0)
|
|
{
|
|
houseErrors++;
|
|
(*thisHouse)->rooms[i].suite = kRoomIsEmpty;
|
|
}
|
|
else
|
|
pidgeonHoles[bitPlace]++;
|
|
}
|
|
}
|
|
|
|
HSetState((Handle)thisHouse, wasState);
|
|
|
|
DisposePtr((Ptr)pidgeonHoles);
|
|
}
|
|
|
|
//-------------------------------------------------------------- CompressHouse
|
|
|
|
// Removes place-holder (deleted) rooms from the middle of the file.
|
|
|
|
void CompressHouse (void)
|
|
{
|
|
short wasFirstRoom, roomNumber, probe;
|
|
char wasState;
|
|
Boolean compressing, probing;
|
|
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
|
|
wasFirstRoom = (*thisHouse)->firstRoom;
|
|
compressing = true;
|
|
roomNumber = (*thisHouse)->nRooms - 1; // start with last room
|
|
do
|
|
{
|
|
if ((*thisHouse)->rooms[roomNumber].suite != kRoomIsEmpty)
|
|
{ // if not an empty roomÉ
|
|
probe = 0; // start looking for empty slot
|
|
probing = true;
|
|
do
|
|
{ // test room at probe to see if empty
|
|
if ((*thisHouse)->rooms[probe].suite == kRoomIsEmpty)
|
|
{ // if it is, copy room there
|
|
(*thisHouse)->rooms[probe] = (*thisHouse)->rooms[roomNumber];
|
|
(*thisHouse)->rooms[roomNumber].suite = kRoomIsEmpty;
|
|
if (roomNumber == wasFirstRoom)
|
|
(*thisHouse)->firstRoom = probe;
|
|
if (roomNumber == wasRoom)
|
|
wasRoom = probe;
|
|
probing = false;
|
|
}
|
|
probe++; // bump probe up to next room
|
|
if ((probing) && (probe >= roomNumber))
|
|
{ // we reached the current room
|
|
probing = false; // we can look no further
|
|
compressing = false; // so we can compress no more
|
|
}
|
|
}
|
|
while (probing);
|
|
}
|
|
roomNumber--; // go on to room preceding
|
|
if (roomNumber <= 0) // stop if we reach the first room
|
|
compressing = false;
|
|
}
|
|
while (compressing);
|
|
|
|
HSetState((Handle)thisHouse, wasState);
|
|
}
|
|
|
|
//-------------------------------------------------------------- LopOffExtraRooms
|
|
|
|
// Deletes all empty rooms hanging off the end of the house file.
|
|
|
|
void LopOffExtraRooms (void)
|
|
{
|
|
long newSize;
|
|
short r, count;
|
|
char wasState;
|
|
Str255 message;
|
|
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
|
|
count = 0;
|
|
r = (*thisHouse)->nRooms; // begin at last room
|
|
do
|
|
{
|
|
r--; // look for trailing empties
|
|
if ((*thisHouse)->rooms[r].suite == kRoomIsEmpty)
|
|
count++;
|
|
else
|
|
r = 0;
|
|
}
|
|
while (r > 0);
|
|
|
|
if (count > 0) // if there were trailing emptiesÉ
|
|
{
|
|
r = (*thisHouse)->nRooms - count;
|
|
newSize = sizeof(houseType) + (sizeof(roomType) * (long)r);
|
|
HUnlock((Handle)thisHouse); // resize house handle (shrink)
|
|
SetHandleSize((Handle)thisHouse, newSize);
|
|
if (MemError() != noErr) // problem?
|
|
{
|
|
ForeColor(redColor);
|
|
GetLocalizedString(16, message);
|
|
SetMessageWindowMessage(message);
|
|
}
|
|
HLock((Handle)thisHouse); // reflect new room count
|
|
(*thisHouse)->nRooms -= count;
|
|
numberRooms = (*thisHouse)->nRooms;
|
|
}
|
|
HSetState((Handle)thisHouse, wasState);
|
|
}
|
|
|
|
//-------------------------------------------------------------- ValidateRoomNumbers
|
|
|
|
// Error check - ensures that the floor and suite numbers are within legal ranges.
|
|
|
|
void ValidateRoomNumbers (void)
|
|
{
|
|
short i, numRooms;
|
|
char wasState;
|
|
Str255 message;
|
|
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
|
|
numRooms = (*thisHouse)->nRooms;
|
|
if (numRooms < 0)
|
|
{
|
|
(*thisHouse)->nRooms = 0;
|
|
numRooms = 0;
|
|
}
|
|
for (i = 0; i < numRooms; i++)
|
|
{
|
|
if ((*thisHouse)->rooms[i].suite != kRoomIsEmpty)
|
|
{
|
|
if (((*thisHouse)->rooms[i].floor > 56) ||
|
|
((*thisHouse)->rooms[i].floor < -7))
|
|
{
|
|
(*thisHouse)->rooms[i].suite = kRoomIsEmpty;
|
|
ForeColor(redColor);
|
|
GetLocalizedString(17, message);
|
|
SetMessageWindowMessage(message);
|
|
houseErrors++;
|
|
ForeColor(blackColor);
|
|
}
|
|
if (((*thisHouse)->rooms[i].suite >= 128) ||
|
|
((*thisHouse)->rooms[i].suite < 0))
|
|
{
|
|
(*thisHouse)->rooms[i].suite = kRoomIsEmpty;
|
|
ForeColor(redColor);
|
|
GetLocalizedString(18, message);
|
|
SetMessageWindowMessage(message);
|
|
houseErrors++;
|
|
ForeColor(blackColor);
|
|
}
|
|
}
|
|
}
|
|
|
|
HSetState((Handle)thisHouse, wasState);
|
|
}
|
|
|
|
//-------------------------------------------------------------- CountUntitledRooms
|
|
|
|
// Returns the number of rooms left "Untitled".
|
|
|
|
void CountUntitledRooms (void)
|
|
{
|
|
short i, numRooms;
|
|
char wasState;
|
|
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
|
|
numRooms = (*thisHouse)->nRooms;
|
|
for (i = 0; i < numRooms; i++)
|
|
{
|
|
if (((*thisHouse)->rooms[i].suite != kRoomIsEmpty) &&
|
|
(EqualString((*thisHouse)->rooms[i].name, "\pUntitled Room", false, true)))
|
|
houseErrors++;
|
|
}
|
|
|
|
HSetState((Handle)thisHouse, wasState);
|
|
}
|
|
|
|
//-------------------------------------------------------------- CheckRoomNameLength
|
|
|
|
// Error check - ensures the length of the room name is legal.
|
|
|
|
void CheckRoomNameLength (void)
|
|
{
|
|
short i, numRooms;
|
|
char wasState;
|
|
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
|
|
numRooms = (*thisHouse)->nRooms;
|
|
for (i = 0; i < numRooms; i++)
|
|
{
|
|
(*thisHouse)->rooms[i].unusedByte = 0;
|
|
|
|
if (((*thisHouse)->rooms[i].suite != kRoomIsEmpty) &&
|
|
((*thisHouse)->rooms[i].name[0] > 27))
|
|
{
|
|
(*thisHouse)->rooms[i].name[0] = 27;
|
|
houseErrors++;
|
|
}
|
|
}
|
|
|
|
HSetState((Handle)thisHouse, wasState);
|
|
}
|
|
|
|
//-------------------------------------------------------------- MakeSureNumObjectsJives
|
|
|
|
// Error check - ensures the actual count of objects equals number of objects.
|
|
|
|
void MakeSureNumObjectsJives (void)
|
|
{
|
|
short i, h, numRooms, count;
|
|
char wasState;
|
|
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
|
|
numRooms = (*thisHouse)->nRooms;
|
|
for (i = 0; i < numRooms; i++)
|
|
{
|
|
if ((*thisHouse)->rooms[i].suite != kRoomIsEmpty)
|
|
{
|
|
count = 0;
|
|
for (h = 0; h < kMaxRoomObs; h++)
|
|
{
|
|
if ((*thisHouse)->rooms[i].objects[h].what != kObjectIsEmpty)
|
|
count++;
|
|
}
|
|
if (count != (*thisHouse)->rooms[i].numObjects)
|
|
{
|
|
houseErrors++;
|
|
(*thisHouse)->rooms[i].numObjects = count;
|
|
}
|
|
}
|
|
}
|
|
|
|
HSetState((Handle)thisHouse, wasState);
|
|
}
|
|
|
|
//-------------------------------------------------------------- KeepAllObjectsLegal
|
|
|
|
// Repeatedly calls KeepObjectLegal() on ALL objects in a house. Wow!
|
|
|
|
void KeepAllObjectsLegal (void)
|
|
{
|
|
short i, h, numRooms;
|
|
char wasState;
|
|
Str255 message;
|
|
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
|
|
numRooms = (*thisHouse)->nRooms;
|
|
for (i = 0; i < numRooms; i++)
|
|
{
|
|
if ((*thisHouse)->rooms[i].suite != kRoomIsEmpty)
|
|
{
|
|
ForceThisRoom(i);
|
|
for (h = 0; h < kMaxRoomObs; h++)
|
|
{
|
|
objActive = h;
|
|
if (thisRoom->objects[objActive].what != kObjectIsEmpty)
|
|
{
|
|
if (!KeepObjectLegal())
|
|
{
|
|
ForeColor(redColor);
|
|
GetLocalizedString(19, message);
|
|
SetMessageWindowMessage(message);
|
|
houseErrors++;
|
|
ForeColor(blackColor);
|
|
DelayTicks(60);
|
|
}
|
|
}
|
|
}
|
|
CopyThisRoomToRoom();
|
|
}
|
|
}
|
|
|
|
HSetState((Handle)thisHouse, wasState);
|
|
}
|
|
|
|
//-------------------------------------------------------------- CheckForStaircasePairs
|
|
|
|
// Ensures that for every up-stair there is a down-stair.
|
|
|
|
void CheckForStaircasePairs (void)
|
|
{
|
|
short i, h, g, numRooms, neighbor;
|
|
char wasState;
|
|
Boolean hasStairs;
|
|
Str255 message;
|
|
|
|
wasState = HGetState((Handle)thisHouse);
|
|
HLock((Handle)thisHouse);
|
|
|
|
numRooms = (*thisHouse)->nRooms;
|
|
for (i = 0; i < numRooms; i++)
|
|
{
|
|
if ((*thisHouse)->rooms[i].suite != kRoomIsEmpty)
|
|
{
|
|
for (h = 0; h < kMaxRoomObs; h++)
|
|
{
|
|
if ((*thisHouse)->rooms[i].objects[h].what == kUpStairs)
|
|
{
|
|
thisRoomNumber = i;
|
|
neighbor = GetNeighborRoomNumber(kNorthRoom);
|
|
if (neighbor == kRoomIsEmpty)
|
|
{
|
|
ForeColor(redColor);
|
|
GetLocalizedString(20, message);
|
|
SetMessageWindowMessage(message);
|
|
ForeColor(blackColor);
|
|
DelayTicks(60);
|
|
}
|
|
else
|
|
{
|
|
hasStairs = false;
|
|
for (g = 0; g < kMaxRoomObs; g++)
|
|
{
|
|
if ((*thisHouse)->rooms[neighbor].objects[g].what ==
|
|
kDownStairs)
|
|
hasStairs = true;
|
|
}
|
|
if (!hasStairs)
|
|
{
|
|
ForeColor(redColor);
|
|
GetLocalizedString(21, message);
|
|
SetMessageWindowMessage(message);
|
|
ForeColor(blackColor);
|
|
DelayTicks(60);
|
|
}
|
|
}
|
|
}
|
|
else if ((*thisHouse)->rooms[i].objects[h].what == kDownStairs)
|
|
{
|
|
thisRoomNumber = i;
|
|
neighbor = GetNeighborRoomNumber(kSouthRoom);
|
|
if (neighbor == kRoomIsEmpty)
|
|
{
|
|
ForeColor(redColor);
|
|
GetLocalizedString(22, message);
|
|
SetMessageWindowMessage(message);
|
|
ForeColor(blackColor);
|
|
DelayTicks(60);
|
|
}
|
|
else
|
|
{
|
|
hasStairs = false;
|
|
for (g = 0; g < kMaxRoomObs; g++)
|
|
{
|
|
if ((*thisHouse)->rooms[neighbor].objects[g].what ==
|
|
kUpStairs)
|
|
hasStairs = true;
|
|
}
|
|
if (!hasStairs)
|
|
{
|
|
ForeColor(redColor);
|
|
GetLocalizedString(23, message);
|
|
SetMessageWindowMessage(message);
|
|
ForeColor(blackColor);
|
|
DelayTicks(60);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
HSetState((Handle)thisHouse, wasState);
|
|
}
|
|
#endif
|
|
|
|
//-------------------------------------------------------------- CheckHouseForProblems
|
|
|
|
// Calls all the above functions and reports (and corrects) errors.
|
|
|
|
void CheckHouseForProblems (void)
|
|
{
|
|
#ifndef COMPILEDEMO
|
|
Str255 message, message2;
|
|
short wasActive;
|
|
|
|
houseErrors = 0;
|
|
CopyThisRoomToRoom();
|
|
wasRoom = thisRoomNumber;
|
|
wasActive = objActive;
|
|
GetLocalizedString(24, message);
|
|
OpenMessageWindow(message);
|
|
|
|
SpinCursor(3);
|
|
GetLocalizedString(25, message);
|
|
SetMessageWindowMessage(message);
|
|
WrapBannerAndTrailer();
|
|
|
|
if (isHouseChecks)
|
|
{
|
|
SpinCursor(3);
|
|
GetLocalizedString(26, message);
|
|
SetMessageWindowMessage(message);
|
|
ValidateNumberOfRooms();
|
|
if (houseErrors != 0)
|
|
{
|
|
GetLocalizedString(27, message);
|
|
SetMessageWindowMessage(message);
|
|
DelayTicks(60);
|
|
houseErrors = 0;
|
|
}
|
|
}
|
|
|
|
if (isHouseChecks)
|
|
{
|
|
SpinCursor(3);
|
|
houseErrors = 0;
|
|
CheckDuplicateFloorSuite();
|
|
if (houseErrors != 0)
|
|
{
|
|
NumToString((long)houseErrors, message);
|
|
GetLocalizedString(28, message2);
|
|
PasStringConcat(message, message2);
|
|
ForeColor(redColor);
|
|
SetMessageWindowMessage(message);
|
|
ForeColor(blackColor);
|
|
DelayTicks(45);
|
|
}
|
|
}
|
|
|
|
SpinCursor(3);
|
|
CompressHouse();
|
|
SpinCursor(3);
|
|
LopOffExtraRooms();
|
|
|
|
if (isHouseChecks)
|
|
{
|
|
SpinCursor(3);
|
|
ValidateRoomNumbers();
|
|
if (houseErrors != 0)
|
|
{
|
|
NumToString((long)houseErrors, message);
|
|
GetLocalizedString(29, message2);
|
|
PasStringConcat(message, message2);
|
|
ForeColor(redColor);
|
|
SetMessageWindowMessage(message);
|
|
ForeColor(blackColor);
|
|
DelayTicks(60);
|
|
}
|
|
}
|
|
|
|
if (isHouseChecks)
|
|
{
|
|
SpinCursor(3);
|
|
houseErrors = 0;
|
|
CountUntitledRooms();
|
|
if (houseErrors != 0)
|
|
{
|
|
NumToString((long)houseErrors, message);
|
|
GetLocalizedString(30, message2);
|
|
PasStringConcat(message, message2);
|
|
ForeColor(blueColor);
|
|
SetMessageWindowMessage(message);
|
|
ForeColor(blackColor);
|
|
DelayTicks(45);
|
|
}
|
|
}
|
|
|
|
if (isHouseChecks)
|
|
{
|
|
SpinCursor(3);
|
|
houseErrors = 0;
|
|
CheckRoomNameLength();
|
|
if (houseErrors != 0)
|
|
{
|
|
NumToString((long)houseErrors, message);
|
|
GetLocalizedString(31, message2);
|
|
PasStringConcat(message, message2);
|
|
ForeColor(blueColor);
|
|
SetMessageWindowMessage(message);
|
|
ForeColor(blackColor);
|
|
DelayTicks(45);
|
|
}
|
|
}
|
|
|
|
if (isHouseChecks)
|
|
{
|
|
SpinCursor(3);
|
|
houseErrors = 0;
|
|
MakeSureNumObjectsJives();
|
|
if (houseErrors != 0)
|
|
{
|
|
NumToString((long)houseErrors, message);
|
|
GetLocalizedString(32, message2);
|
|
PasStringConcat(message, message2);
|
|
ForeColor(redColor);
|
|
SetMessageWindowMessage(message);
|
|
ForeColor(blackColor);
|
|
DelayTicks(60);
|
|
}
|
|
}
|
|
|
|
if (isHouseChecks)
|
|
{
|
|
SpinCursor(3);
|
|
houseErrors = 0;
|
|
GetLocalizedString(33, message);
|
|
SetMessageWindowMessage(message);
|
|
KeepAllObjectsLegal();
|
|
if (houseErrors != 0)
|
|
{
|
|
NumToString((long)houseErrors, message);
|
|
GetLocalizedString(34, message2);
|
|
PasStringConcat(message, message2);
|
|
ForeColor(redColor);
|
|
SetMessageWindowMessage(message);
|
|
ForeColor(blackColor);
|
|
DelayTicks(60);
|
|
}
|
|
}
|
|
|
|
if (isHouseChecks)
|
|
{
|
|
SpinCursor(3);
|
|
houseErrors = 0;
|
|
CheckForStaircasePairs();
|
|
}
|
|
|
|
if (isHouseChecks)
|
|
{
|
|
SpinCursor(3);
|
|
if (CountStarsInHouse() < 1)
|
|
{
|
|
ForeColor(redColor);
|
|
GetLocalizedString(35, message);
|
|
SetMessageWindowMessage(message);
|
|
ForeColor(blackColor);
|
|
DelayTicks(60);
|
|
}
|
|
}
|
|
|
|
InitCursor();
|
|
CloseMessageWindow();
|
|
ForceThisRoom(wasRoom);
|
|
objActive = wasActive;
|
|
#endif
|
|
}
|
|
|