Any raw cave data for this boulder-dash level?

Everything about the old and new Boulder Dash games for C64, Atari, ...

Moderator: Admin

User avatar
paul_nicholls
Member
Posts: 108
Joined: Sun Dec 12, 2010 6:16 am
Location: Tasmania, Australia

Any raw cave data for this boulder-dash level?

Post by paul_nicholls »

Hi all,
I would love to test out this level in the video:
http://www.youtube.com/watch?v=oeoWLB8i ... re=related

in my boulder-dash inspired game, but I don't know what level (or version) it is from, or what cave data was used...

The video says level 1, but it isn't level 1 for Boulder-dash I is it?

Does any of you have the raw cave data, like shown here for this level?:
http://www.elmerproductions.com/sp/peterb/cavedata.h

If I had the data, I can load it into my game as I have just finished that part :)

cheers,
Paul
subotai
Member
Posts: 251
Joined: Sun Jan 25, 2009 4:19 pm

Post by subotai »

Hey Paul,

It seems that you don't know Bd1 very well ;-)
paul_nicholls wrote:The video says level 1, but it isn't level 1 for Boulder-dash I is it?
Sure it is. It's Cave I in Level 1.

Check the bdcff files on this homepage to get the leveldata. But beware, some of them seem not to be accurate. If I remember right, the starting direction of the enemies is not always accurate and makes some caves unsolvable. But I'm not sure about this. It has been years ago, I worked with these bdcff files.

If you have trouble generating the cave data, you can load the bdcff file into Gdash and convert the cave to a map. Use Tools - Convert to map in the cave editor.

Richard
User avatar
paul_nicholls
Member
Posts: 108
Joined: Sun Dec 12, 2010 6:16 am
Location: Tasmania, Australia

Post by paul_nicholls »

LOL ok, thanks subotai :)

I didn't try all the caves in the cave data I had, and I haven't played boulder dash for real that much in a while :)

hmm...when I try decoding cave I, I don't get completely the correct objects - I get a bunch of dirt too as in the original level, but I think some of it is in the wrong place (compared to the video here):
http://www.youtube.com/watch?v=2SkrLb76D3k

I think something is either wrong with my cave data converter, or the data - most likely my converter! :D

here is a screenshot of the cave when it is decoded:
Image

cheers,
Paul
User avatar
paul_nicholls
Member
Posts: 108
Joined: Sun Dec 12, 2010 6:16 am
Location: Tasmania, Australia

Post by paul_nicholls »

I think I might have fixed the issue...it seems I was starting at 0 for the y location instead of starting from 1, like here:
http://www.boulderdash.nl/forum/viewtop ... dom+number

Code: Select all

  // fill in with null (Titanium Wall)
  for y := 0 to FHeight - 1 do
    for x := 0 to FWidth - 1 do
      SetObjectAt(cMainLayer,Position(x,0),cObjTitaniumWall);

  // random fill in level
  // Initialize the values of both random seeds:
  RandSeed1 := 0;
  RandSeed2 := CaveDataHeader.RandomiserSeedValueDifficulty[Difficulty]; // This is the seed-value from the cave

  // Fill the rest of the cave
  for y := 1 to FHeight - 1 do
  begin
    for x := 0 to FWidth - 1 do
    begin
      Item := cObjDirt; // Default item is dirt!
      NextRandom(RandSeed1, RandSeed2); // Draw a random number between 0 and 255.

      // Determine which item should be placed:
      for k := 1 to  High(CaveDataHeader.ProbabilityObject) do
      begin
        if (RandSeed1 < CaveDataHeader.ProbabilityObject[k]) then
        begin
          Item := BDObjectToEngineObject(CaveDataHeader.RandomObjectNumber[k]);
        end;
      end;

      SetObjectAt(cMainLayer,Position(x,y),Item);
    end;
  end;
cheers,
Paul
User avatar
paul_nicholls
Member
Posts: 108
Joined: Sun Dec 12, 2010 6:16 am
Location: Tasmania, Australia

Post by paul_nicholls »

Oh, just one other thing...do you think I should make my dirt a little bit darker, and not such a light brown?

Or do you like it as it is?

cheers,
Paul
subotai
Member
Posts: 251
Joined: Sun Jan 25, 2009 4:19 pm

Post by subotai »

I don't know if it's possible to link to other threads in this forum. Search for the following terms: RandSeed Randomfill BDCFF

You should find a thread where you can download Marek's Dash-FAQ (Bdfaq.zip). Or just visit his homepage. The archive includes an example in Pascal. If you can't get it work, I can also post my code which is 99% based on Marek's code ;-).

In my opinion, the color of dirt could be a bit darker, but not too dark. But your graphics look much better than mine ;-). Can't wait 'til you release your game.
User avatar
paul_nicholls
Member
Posts: 108
Joined: Sun Dec 12, 2010 6:16 am
Location: Tasmania, Australia

Post by paul_nicholls »

subotai wrote:I don't know if it's possible to link to other threads in this forum. Search for the following terms: RandSeed Randomfill BDCFF

You should find a thread where you can download Marek's Dash-FAQ (Bdfaq.zip). Or just visit his homepage. The archive includes an example in Pascal. If you can't get it work, I can also post my code which is 99% based on Marek's code ;-).

In my opinion, the color of dirt could be a bit darker, but not too dark. But your graphics look much better than mine ;-). Can't wait 'til you release your game.
Thanks mate :)

I found this which seems to have the zip file you mentioned:
http://www.boulder-dash.nl/forum/viewtopic.php?t=217

hmm...I'm finding that code a bit confusing as the random number generator and level filler seem to be merged, and that bits are in German :)

Any chance you could post your bit of code?

PS. just add in any link into a post to for it to work ;)

cheers,
Paul
User avatar
paul_nicholls
Member
Posts: 108
Joined: Sun Dec 12, 2010 6:16 am
Location: Tasmania, Australia

Post by paul_nicholls »

Here is my code:

// cave data and call to the cave decoder

Code: Select all

procedure TTheProbe.LoadLevel;
type
  PCaveInfo = ^TCaveInfo;
  TCaveInfo = record
    CavePntr    : PByte;
    CaveSize    : Integer;
    Intermission: Boolean;
  end;

const
  cCave1: array[1..58] of Byte =
  (
  $01,$14,$0A,$0F,$0A,$0B,$0C,$0D,$0E,$0C,$0C,$0C,$0C,$0C,$96,$6E,
  $46,$28,$1E,$08,$0B,$09,$D4,$20,$00,$10,$14,$00,$3C,$32,$09,$00,
  $42,$01,$09,$1E,$02,$42,$09,$10,$1E,$02,$25,$03,$04,$04,$26,$12,
  $FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave2: array[1..98] of Byte =
  (
  $02,$14,$14,$32,$03,$00,$01,$57,$58,$0A,$0C,$09,$0D,$0A,$96,$6E,
  $46,$46,$46,$0A,$04,$09,$00,$00,$00,$10,$14,$08,$3C,$32,$09,$02,
  $42,$01,$08,$26,$02,$42,$01,$0F,$26,$02,$42,$08,$03,$14,$04,$42,
  $10,$03,$14,$04,$42,$18,$03,$14,$04,$42,$20,$03,$14,$04,$40,$01,
  $05,$26,$02,$40,$01,$0B,$26,$02,$40,$01,$12,$26,$02,$40,$14,$03,
  $14,$04,$25,$12,$15,$04,$12,$16,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave3: array[1..48] of Byte =
  (
  $03,$00,$0F,$00,$00,$32,$36,$34,$37,$18,$17,$18,$17,$15,$96,$64,
  $5A,$50,$46,$09,$08,$09,$04,$00,$02,$10,$14,$00,$64,$32,$09,$00,
  $25,$03,$04,$04,$27,$14,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave4: array[1..84] of Byte =
  (
  $04,$14,$05,$14,$00,$6E,$70,$73,$77,$24,$24,$24,$24,$24,$78,$64,
  $50,$3C,$32,$04,$08,$09,$00,$00,$10,$00,$00,$00,$14,$00,$00,$00,
  $25,$01,$03,$04,$26,$16,$81,$08,$0A,$04,$04,$00,$30,$0A,$0B,$81,
  $10,$0A,$04,$04,$00,$30,$12,$0B,$81,$18,$0A,$04,$04,$00,$30,$1A,
  $0B,$81,$20,$0A,$04,$04,$00,$30,$22,$0B,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave5: array[1..144] of Byte =
  (
  $05,$14,$32,$5A,$00,$00,$00,$00,$00,$04,$05,$06,$07,$08,$96,$78,
  $5A,$3C,$1E,$09,$0A,$09,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  $25,$01,$03,$04,$27,$16,$80,$08,$0A,$03,$03,$00,$80,$10,$0A,$03,
  $03,$00,$80,$18,$0A,$03,$03,$00,$80,$20,$0A,$03,$03,$00,$14,$09,
  $0C,$08,$0A,$0A,$14,$11,$0C,$08,$12,$0A,$14,$19,$0C,$08,$1A,$0A,
  $14,$21,$0C,$08,$22,$0A,$80,$08,$10,$03,$03,$00,$80,$10,$10,$03,
  $03,$00,$80,$18,$10,$03,$03,$00,$80,$20,$10,$03,$03,$00,$14,$09,
  $12,$08,$0A,$10,$14,$11,$12,$08,$12,$10,$14,$19,$12,$08,$1A,$10,
  $14,$21,$12,$08,$22,$10,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave6: array[1..154] of Byte =
  (
  $06,$14,$28,$3C,$00,$14,$15,$16,$17,$04,$06,$07,$08,$08,$96,
  $78,$64,$5A,$50,$0E,$0A,$09,$00,$00,$10,$00,$00,$00,$32,$00,$00,
  $00,$82,$01,$03,$0A,$04,$00,$82,$01,$06,$0A,$04,$00,$82,$01,$09,
  $0A,$04,$00,$82,$01,$0C,$0A,$04,$00,$41,$0A,$03,$0D,$04,$14,$03,
  $05,$08,$04,$05,$14,$03,$08,$08,$04,$08,$14,$03,$0B,$08,$04,$0B,
  $14,$03,$0E,$08,$04,$0E,$82,$1D,$03,$0A,$04,$00,$82,$1D,$06,$0A,
  $04,$00,$82,$1D,$09,$0A,$04,$00,$82,$1D,$0C,$0A,$04,$00,$41,$1D,
  $03,$0D,$04,$14,$24,$05,$08,$23,$05,$14,$24,$08,$08,$23,$08,$14,
  $24,$0B,$08,$23,$0B,$14,$24,$0E,$08,$23,$0E,$25,$03,$14,$04,$26,
  $14,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave7: array[1..81] of Byte =
  (
  $07,$4B,$0A,$14,$02,$07,$08,$0A,$09,$0F,$14,$19,$19,$19,
  $78,$78,$78,$78,$78,$09,$0A,$0D,$00,$00,$00,$10,$08,$00,$64,$28,
  $02,$00,$42,$01,$07,$0C,$02,$42,$1C,$05,$0B,$02,$7A,$13,$15,$02,
  $02,$14,$04,$06,$14,$04,$0E,$14,$04,$16,$14,$22,$04,$14,$22,$0C,
  $14,$22,$16,$25,$14,$03,$04,$27,$07,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave8: array[1..96] of Byte =
  (
  $08,$14,$0A,$14,$01,$03,
  $04,$05,$06,$0A,$0F,$14,$14,$14,$78,$6E,$64,$5A,$50,$02,$0E,$09,
  $00,$00,$00,$10,$08,$00,$5A,$32,$02,$00,$14,$04,$06,$14,$22,$04,
  $14,$22,$0C,$04,$00,$05,$25,$14,$03,$42,$01,$07,$0C,$02,$42,$01,
  $0F,$0C,$02,$42,$1C,$05,$0B,$02,$42,$1C,$0D,$0B,$02,$43,$0E,$11,
  $08,$02,$14,$0C,$10,$00,$0E,$12,$14,$13,$12,$41,$0E,$0F,$08,$02,
  $FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave9: array[1..76] of Byte =
  (
  $09,$14,$05,$0A,$64,$89,$8C,$FB,$33,$4B,$4B,$50,$55,$5A,$96,
  $96,$82,$82,$78,$08,$04,$09,$00,$00,$10,$14,$00,$00,$F0,$78,$00,
  $00,$82,$05,$0A,$0D,$0D,$00,$01,$0C,$0A,$82,$19,$0A,$0D,$0D,$00,
  $01,$1F,$0A,$42,$11,$12,$09,$02,$40,$11,$13,$09,$02,$25,$07,$0C,
  $04,$08,$0C,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave10: array[1..110] of Byte =
  (
  $0A,$14,$19,$3C,$00,$00,$00,$00,$00,$0C,$0C,$0C,
  $0C,$0C,$96,$82,$78,$6E,$64,$06,$08,$09,$00,$00,$00,$00,$00,$00,
  $00,$00,$00,$00,$25,$0D,$03,$04,$27,$16,$54,$05,$04,$11,$03,$54,
  $15,$04,$11,$05,$80,$05,$0B,$11,$03,$08,$C2,$01,$04,$15,$11,$00,
  $0D,$04,$C2,$07,$06,$0D,$0D,$00,$0D,$06,$C2,$09,$08,$09,$09,$00,
  $0D,$08,$C2,$0B,$0A,$05,$05,$00,$0D,$0A,$82,$03,$06,$03,$0F,$08,
  $00,$04,$06,$54,$04,$10,$04,$04,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave11: array[1..111] of Byte =
  (
  $0B,$14,$32,$00,$00,$04,$66,
  $97,$64,$06,$06,$06,$06,$06,$78,$78,$96,$96,$F0,$0B,$08,$09,$00,
  $00,$00,$10,$08,$00,$64,$50,$02,$00,$42,$0A,$03,$09,$04,$42,$14,
  $03,$09,$04,$42,$1E,$03,$09,$04,$42,$09,$16,$09,$00,$42,$0C,$0F,
  $11,$02,$42,$05,$0B,$09,$02,$42,$0F,$0B,$09,$02,$42,$19,$0B,$09,
  $02,$42,$1C,$13,$0B,$01,$14,$04,$03,$14,$0E,$03,$14,$18,$03,$14,
  $22,$03,$14,$04,$16,$14,$23,$15,$25,$14,$14,$04,$26,$11,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave12: array[1..115] of Byte =
  (
  $0C,$14,$14,$00,$00,$3C,$02,$3B,$66,$13,$13,$0E,$10,$15,$B4,$AA,$A0,
  $A0,$A0,$0C,$0A,$09,$00,$00,$00,$10,$14,$00,$3C,$32,$09,$00,$42,
  $0A,$05,$12,$04,$42,$0E,$05,$12,$04,$42,$12,$05,$12,$04,$42,$16,
  $05,$12,$04,$42,$02,$06,$0B,$02,$42,$02,$0A,$0B,$02,$42,$02,$0E,
  $0F,$02,$42,$02,$12,$0B,$02,$81,$1E,$04,$04,$04,$00,$08,$20,$05,
  $81,$1E,$09,$04,$04,$00,$08,$20,$0A,$81,$1E,$0E,$04,$04,$00,$08,
  $20,$0F,$25,$03,$14,$04,$27,$16,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave13: array[1..71] of Byte =
  (
  $0D,$8C,$05,$08,$00,$01,$02,
  $03,$04,$32,$37,$3C,$46,$50,$A0,$9B,$96,$91,$8C,$06,$08,$0D,$00,
  $00,$10,$00,$00,$00,$28,$00,$00,$00,$25,$12,$03,$04,$0A,$03,$3A,
  $14,$03,$42,$05,$12,$1E,$02,$70,$05,$13,$1E,$02,$50,$05,$14,$1E,
  $02,$C1,$05,$15,$1E,$02,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave14: array[1..99] of Byte =
  (
  $0E,$14,$0A,$14,$00,$00,$00,$00,$00,
  $1E,$23,$28,$2A,$2D,$96,$91,$8C,$87,$82,$0C,$08,$09,$00,$00,$10,
  $00,$00,$00,$00,$00,$00,$00,$81,$0A,$0A,$0D,$0D,$00,$70,$0B,$0B,
  $0C,$03,$C1,$0C,$0A,$03,$0D,$C1,$10,$0A,$03,$0D,$C1,$14,$0A,$03,
  $0D,$50,$16,$08,$0C,$02,$48,$16,$07,$0C,$02,$C1,$17,$06,$03,$04,
  $C1,$1B,$06,$03,$04,$C1,$1F,$06,$03,$04,$25,$03,$03,$04,$27,$14,
  $FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave15: array[1..68] of Byte =
  (
  $0F,$08,$0A,$14,$01,$1D,$1E,$1F,$20,$0F,$14,$14,$19,$1E,$78,
  $78,$78,$78,$8C,$08,$0E,$09,$00,$00,$00,$10,$08,$00,$64,$50,$02,
  $00,$42,$02,$04,$0A,$03,$42,$0F,$0D,$0A,$01,$41,$0C,$0E,$03,$02,
  $43,$0C,$0F,$03,$02,$04,$14,$16,$25,$14,$03,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave16: array[1..104] of Byte =
  (
  $10,$14,$0A,$14,
  $01,$78,$81,$7E,$7B,$0C,$0F,$0F,$0F,$0C,$96,$96,$96,$96,$96,$09,
  $0A,$09,$00,$00,$10,$00,$00,$00,$32,$00,$00,$00,$25,$01,$03,$04,
  $27,$04,$81,$08,$13,$04,$04,$00,$08,$0A,$14,$C2,$07,$0A,$06,$08,
  $43,$07,$0A,$06,$02,$81,$10,$13,$04,$04,$00,$08,$12,$14,$C2,$0F,
  $0A,$06,$08,$43,$0F,$0A,$06,$02,$81,$18,$13,$04,$04,$00,$08,$1A,
  $14,$81,$20,$13,$04,$04,$00,$08,$22,$14,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave17: array[1..69] of Byte =
  (
  $11,$14,$1E,$00,$0A,$0B,$0C,$0D,$0E,$06,$06,$06,$06,$06,$0A,$0A,
  $0A,$0A,$0A,$0E,$02,$09,$00,$00,$00,$14,$00,$00,$FF,$09,$00,$00,
  $87,$00,$02,$28,$16,$07,$87,$00,$02,$14,$0C,$00,$32,$0A,$0C,$10,
  $0A,$04,$01,$0A,$05,$25,$03,$05,$04,$12,$0C,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave18: array[1..95] of Byte =
  (
  $12,$14,$0A,$00,$0A,$0B,$0C,$0D,$0E,
  $10,$10,$10,$10,$10,$0F,$0F,$0F,$0F,$0F,$06,$0F,$09,$00,$00,$00,
  $00,$00,$00,$00,$00,$00,$00,$87,$00,$02,$28,$16,$07,$87,$00,$02,
  $14,$0C,$01,$50,$01,$03,$09,$03,$48,$02,$03,$08,$03,$54,$01,$05,
  $08,$03,$50,$01,$06,$07,$03,$50,$12,$03,$09,$05,$54,$12,$05,$08,
  $05,$50,$12,$06,$07,$05,$25,$01,$04,$04,$12,$04,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave19: array[1..71] of Byte =
  (
  $13,$04,$0A,
  $00,$0A,$0B,$0C,$0D,$0E,$0E,$0E,$0E,$0E,$0E,$14,$14,$14,$14,$14,
  $06,$08,$09,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$87,$00,$02,
  $28,$16,$07,$87,$00,$02,$14,$0C,$00,$54,$01,$0C,$12,$02,$88,$0F,
  $09,$04,$04,$08,$25,$08,$03,$04,$12,$07,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCave20: array[1..86] of Byte =
  (
  $14,$03,$1E,$00,$00,
  $00,$00,$00,$00,$06,$06,$06,$06,$06,$14,$14,$14,$14,$14,$06,$08,
  $09,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$87,$00,$02,$28,$16,
  $07,$87,$00,$02,$14,$0C,$01,$D0,$0B,$03,$03,$02,$80,$0B,$07,$03,
  $06,$00,$43,$0B,$06,$03,$02,$43,$0B,$0A,$03,$02,$50,$08,$07,$03,
  $03,$25,$03,$03,$04,$09,$0A,$FF,
  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff );

  cCaves: array[1..20] of TCaveInfo = (
    (CavePntr: @cCave1 ; CaveSize: SizeOf(cCave1 ); Intermission: False),
    (CavePntr: @cCave2 ; CaveSize: SizeOf(cCave2 ); Intermission: False),
    (CavePntr: @cCave3 ; CaveSize: SizeOf(cCave3 ); Intermission: False),
    (CavePntr: @cCave4 ; CaveSize: SizeOf(cCave4 ); Intermission: False),
    (CavePntr: @cCave5 ; CaveSize: SizeOf(cCave5 ); Intermission: False),
    (CavePntr: @cCave6 ; CaveSize: SizeOf(cCave6 ); Intermission: False),
    (CavePntr: @cCave7 ; CaveSize: SizeOf(cCave7 ); Intermission: False),
    (CavePntr: @cCave8 ; CaveSize: SizeOf(cCave8 ); Intermission: False),
    (CavePntr: @cCave9 ; CaveSize: SizeOf(cCave9 ); Intermission: False),
    (CavePntr: @cCave10; CaveSize: SizeOf(cCave10); Intermission: False),
    (CavePntr: @cCave11; CaveSize: SizeOf(cCave11); Intermission: False),
    (CavePntr: @cCave12; CaveSize: SizeOf(cCave12); Intermission: False),
    (CavePntr: @cCave13; CaveSize: SizeOf(cCave13); Intermission: False),
    (CavePntr: @cCave14; CaveSize: SizeOf(cCave14); Intermission: False),
    (CavePntr: @cCave15; CaveSize: SizeOf(cCave15); Intermission: False),
    (CavePntr: @cCave16; CaveSize: SizeOf(cCave16); Intermission: False),
    (CavePntr: @cCave17; CaveSize: SizeOf(cCave17); Intermission: True),
    (CavePntr: @cCave18; CaveSize: SizeOf(cCave18); Intermission: True),
    (CavePntr: @cCave19; CaveSize: SizeOf(cCave19); Intermission: True),
    (CavePntr: @cCave20; CaveSize: SizeOf(cCave20); Intermission: True)
  );

var
  w,h,x,y: Integer;
  c: AnsiChar;
  sl: TStringList;
  Obj: PEngineObject;
  SentryData: TSentryData;
  CaveDataStream: TMemoryStream;
  CaveNumber: Integer;
begin
 CaveDataStream := TMemoryStream.Create;
  try
    CaveNumber := 9;
    CaveDataStream.Write(cCaves[CaveNumber].CavePntr^,cCaves[CaveNumber].CaveSize);

    CaveDataStream.Seek(0,soFromBeginning);
    FProbeEngine.LoadLevelFromBDCaveDataStream(CaveDataStream,1,cCaves[CaveNumber].Intermission);
  finally
    CaveDataStream.Free;
  end;
end;
//random number generator (seems to work)

Code: Select all

procedure TTheProbeEngine.NextRandom(var RandSeed1,RandSeed2: Integer);
var
  TempRand1 : SmallInt;
  TempRand2 : SmallInt;
  carry     : SmallInt;
  Result    : SmallInt;
begin
  TempRand1 := (RandSeed1 and $0001) * $0080;   (* Bugfix! *)
  TempRand2 := (RandSeed2 shr 1) and $007F;
  Result    := (RandSeed2) + (RandSeed2 and $0001) * $0080;
  carry     := Ord(Result > $00FF); // carry is 0 if Result <= $00FF, otherwise is 1
  Result    := Result and $00FF;
  Result    := Result + carry + $13;
  carry     := Ord(Result > $00FF); // carry is 0 if Result <= $00FF, otherwise is 1
  RandSeed2 := Result and $00FF;
  Result    := RandSeed1 + carry + TempRand1;
  carry     := Ord(Result > $00FF); // carry is 0 if Result <= $00FF, otherwise is 1
  Result    := Result and $00FF;
  Result    := Result + carry + TempRand2;
  RandSeed1 := Result and $00FF;
end;
// level decoder and writer

Code: Select all

type
  PCaveDataHeader = ^TCaveDataHeader;
  TCaveDataHeader = packed record
    CaveNumber                            : Byte;
    MagicWallMillingTimeAndMaxAmoebaTime  : Byte;
    InitialDiamondValue                   : Byte;
    ExtraDiamondValue                     : Byte;
    RandomiserSeedValueDifficulty         : array[1..5] of Byte;
    DiamondsNeededDifficulty              : array[1..5] of Byte;
    CaveTimeDifficulty                    : array[1..5] of Byte;
    BackgroundColour1                     : Byte;
    BackgroundColour2                     : Byte;
    ForegroundColour                      : Byte;
    unused                                : array[0..1] of Byte;
    RandomObjectNumber                    : array[1..4] of Byte;
    ProbabilityObject                     : array[1..4] of Byte;
  end;

procedure TTheProbeEngine.LoadLevelFromBDCaveDataStream(Stream: TStream; Difficulty: Integer; IsIntermission: Boolean);
var
  CaveDataHeader: TCaveDataHeader;
  Data          : Byte;
  Index         : Integer;
  RandSeed1     : Integer;
  RandSeed2     : Integer;
  Item          : LongWord;
  x,y,k         : Integer;
  StrucCode     : Byte;
  BDItem        : Byte;

  procedure SingleObject;
  var
    x: Byte; //column
    y: Byte; //row
  begin
    Stream.Read(x,SizeOf(x));
    Stream.Read(y,SizeOf(y));

    // compensate for cave going from 2...(h - 1) vertically
    y := y - 2;

    SetObjectAt(cMainLayer,Position(x,y),BDObjectToEngineObject(BDItem));
  end;

  procedure DrawLine;
  const
    cDir: array[0..7] of TPosition = (
      (x:  0; y: -1), // up
      (x: +1; y: -1), // up/right
      (x: +1; y:  0), // right
      (x: +1; y: +1), // down/right
      (x:  0; y: +1), // down
      (x: -1; y: +1), // down/left
      (x: -1; y:  0), // left
      (x: -1; y: -1)  // up/left
    );
  var
    x: byte; //begin column
    y: byte; //begin row
    l: byte; //length
    d: byte; //direction code (0=up, 1=up/right, 2=right, 3=down/right, 4=down, 5=down/left, 6=left, 7=up/left)  begin
  begin
    Stream.Read(x,SizeOf(x));
    Stream.Read(y,SizeOf(y));
    Stream.Read(l,SizeOf(l));
    Stream.Read(d,SizeOf(d));

    // compensate for cave going from 2...(h - 1) vertically
    y := y - 2;

    while l > 0 do
    begin
      SetObjectAt(cMainLayer,Position(x,y),BDObjectToEngineObject(BDItem));
      x := x + cDir[d].x;
      y := y + cDir[d].y;
      Dec(l);
    end;
  end;

  procedure DrawFilledRect;
  var
    x: byte; // top left column
    y: byte; // top left row
    l: byte; // length
    h: byte; // height
    o: byte; // object to fill with
    tx,ty: Integer;
  begin
    Stream.Read(x,SizeOf(x));
    Stream.Read(y,SizeOf(y));
    Stream.Read(l,SizeOf(l));
    Stream.Read(h,SizeOf(h));
    Stream.Read(o,SizeOf(o));

    // compensate for cave going from 2...(h - 1) vertically
    y := y - 2;

    o := o and $3F;

    for ty := 0 to h - 1 do
      for tx := 0 to l - 1 do
        if (ty = 0) or (ty = (h - 1)) or
           (tx = 0) or (tx = (l - 1)) then
          // edge item
          SetObjectAt(cMainLayer,Position(x+tx,y+ty),BDObjectToEngineObject(BDItem))
        else
          // fill item
          SetObjectAt(cMainLayer,Position(x+tx,y+ty),BDObjectToEngineObject(o));
  end;

  procedure DrawRect;
  var
    x: byte; // top left column
    y: byte; // top left row
    l: byte; // length
    h: byte; // height
    tx,ty: Integer;
  begin
    Stream.Read(x,SizeOf(x));
    Stream.Read(y,SizeOf(y));
    Stream.Read(l,SizeOf(l));
    Stream.Read(h,SizeOf(h));

    // compensate for cave going from 2...(h - 1) vertically
    y := y - 2;

    for ty := 0 to h - 1 do
      for tx := 0 to l - 1 do
        if (ty = 0) or (ty = (h - 1)) or
           (tx = 0) or (tx = (l - 1)) then
          SetObjectAt(cMainLayer,Position(x+tx,y+ty),BDObjectToEngineObject(BDItem));
  end;
begin
  if IsIntermission then
    SetBounds(cLayerCount,22,12)
  else
    SetBounds(cLayerCount,40,22);

  // read in header
  Stream.Read(CaveDataHeader,SizeOf(CaveDataHeader));

  FCrystalQuota := CaveDataHeader.DiamondsNeededDifficulty[Difficulty];
  FCrystalsLeft := FCrystalQuota;
  FCrystalCount := 0;

  // fill in with null (Titanium Wall)
  for y := 0 to FHeight - 1 do
    for x := 0 to FWidth - 1 do
      SetObjectAt(cMainLayer,Position(x,0),cObjTitaniumWall);

  // random fill in level
  // Initialize the values of both random seeds:
  RandSeed1 := 0;
  RandSeed2 := CaveDataHeader.RandomiserSeedValueDifficulty[Difficulty]; // This is the seed-value from the cave

  // Fill the rest of the cave
  for y := 1 to FHeight - 1 do
  begin
    for x := 0 to FWidth - 1 do
    begin
      Item := cObjDirt; // Default item is dirt!
      NextRandom(RandSeed1, RandSeed2); // Draw a random number between 0 and 255.

      // Determine which item should be placed:
      for k := 1 to  High(CaveDataHeader.ProbabilityObject) do
      begin
        if (RandSeed1 < CaveDataHeader.ProbabilityObject[k]) then
        begin
          Item := BDObjectToEngineObject(CaveDataHeader.RandomObjectNumber[k]);
        end;
      end;

      SetObjectAt(cMainLayer,Position(x,y),Item);
    end;
  end;

  // read and decode cave data
  Index := 0;
  Data  := 0;
  while (Data <> $FF) and (Stream.Position < Stream.Size) do
  begin
    Stream.Read(Data,SizeOf(Data));

    if Data <> $FF then
    begin
      StrucCode := (Data shr 6) and 3;
      BDItem    := Data and $3F;
      case StrucCode of
        0 : SingleObject;
        1 : DrawLine;
        2 : DrawFilledRect;
        3 : DrawRect;
      else
      end;
    end
    else
      Break;
  end;

  // Fill edges with titanium walls
  for x := 0 to FWidth - 1 do
  begin
    SetObjectAt(cMainLayer,Position(x,0),cObjTitaniumWall);
    SetObjectAt(cMainLayer,Position(x,FHeight - 1),cObjTitaniumWall);
  end;

  for y := 0 to FHeight - 1 do
  begin
    SetObjectAt(cMainLayer,Position(0,y),cObjTitaniumWall);
    SetObjectAt(cMainLayer,Position(FWidth - 1,0),cObjTitaniumWall);
  end;

  BackupLevel;
end;
cheers,
Paul
subotai
Member
Posts: 251
Joined: Sun Jan 25, 2009 4:19 pm

Post by subotai »

I must admit that I've not spent any time trying to find out, how it exactly works. So it's mostly copy and paste code and surely not optimized.

Code: Select all

Var Map:Array[0..879] of Byte;

procedure RandomFill_Objects(MapWidth, MapHeight:Integer; Randseed:Integer; ObjectState:Byte; Probability:Integer; Level:Integer; Var Seed1, Seed2:Byte);
  var
    Counter:Integer;
    shuffel1, shuffel2, shuffel3, shuffel4, ar, xr, yr : integer;
    carry : shortint;
    zy,zx,xlen:Integer;

    hoehe, breite:Integer;
    menge,
    item:Array[0..3] of Integer;


  function rorc(ar:integer):integer;
    var carbak: shortint;
    begin
      carbak:=carry;
      carry:=ar and 1;
      rorc:=128*carbak+(ar div 2);
    end;
  begin

hoehe:=MapHeight; //Stellwall wird automatisch abgezogen!
Breite:=MapWidth;

menge[0]:=0;
menge[1]:=0;
menge[2]:=0;
menge[3]:=Probability; //Boulder
item[0]:=1;
item[1]:=2;
item[2]:=3;
item[3]:=4;


    xlen:=Breite;
    shuffel1:=Randseed;
    shuffel2:=0;
    for zy:=1 to hoehe-2 do begin
      for zx:=0 to pred(breite) do begin
        xr:=1;
        ar:=shuffel2;
        ar:=rorc(ar);
        ar:=rorc(ar);
        shuffel3:=ar and 128;
        ar:=shuffel1;
        ar:=rorc(ar);
        shuffel4:=ar and 127;
        ar:=shuffel1;
        ar:=rorc(ar);
        ar:=rorc(ar);
        ar:=ar and 128;
        carry:=0;
        ar:=shuffel1+ar;
        if ar>255 then begin
          carry:=1;
          ar:=ar and 255;
        end;
        ar:=ar+carry+19;
        if ar>255 then begin
          carry:=1;
          ar:=ar and 255;
        end else begin
          carry:=0;
        end;
        shuffel1:=ar;
        ar:=shuffel2;
        ar:=ar+carry+shuffel3;
        if ar>255 then begin
          carry:=1;
          ar:=ar and 255;
        end else begin
          carry:=0;
        end;
        ar:=ar+carry+shuffel4;
        if ar>255 then begin
          carry:=1;
          ar:=ar and 255;
        end else begin
          carry:=0;
        end;
        shuffel2:=ar;
        for yr:=0 to 3 do begin
          if menge[yr]>ar then begin
            xr:=item[yr];
          end;
        end;
        if (zx>0) and (zx<pred(xlen)) then
        begin

        IF xr=4 then
           BEGIN
           Counter:=(zy-0)*40+zx;
           Map[Counter]:=ObjectState;
           END;

        end;
      end;
    end;

 Seed1:=Shuffel1;
 Seed2:=Shuffel2;

  end;

Code: Select all

//i = index of random element
//RandSeed[Level] =  Initial randomiser seed value for difficulty level (level = 0..4)
//Caveindex (0..19)

For i:=1 to 4 do
RandomFill_Objects(40,22,RandSeed[Level],RandomElement[i],Element_Prob[i],Caveindex,Slime_Seed1,Slime_Seed2);
LogicDeLuxe wrote:Note that after this routine has finished, the bounding steel wall is placed over the extremeties of the cave.
And after that, you can draw the single elements.

The order of these steps is important. Check the very good InsideFaq (in Englisch) on Marek's website.

EDIT: This is also valid for intermissions. So the Mapwidth and MapHeight are in fact constant values. By the way, as far as I know, in intermissions, the whole cave (40*22 fields) is used. There are some games that take advantage of this.
Last edited by subotai on Fri Sep 16, 2011 1:17 am, edited 1 time in total.
User avatar
paul_nicholls
Member
Posts: 108
Joined: Sun Dec 12, 2010 6:16 am
Location: Tasmania, Australia

Post by paul_nicholls »

Thanks for that I will take a closer look, and look at Marek's website :)

cheers,
Paul
User avatar
paul_nicholls
Member
Posts: 108
Joined: Sun Dec 12, 2010 6:16 am
Location: Tasmania, Australia

Post by paul_nicholls »

subotai wrote:Check the very good InsideFaq (in Englisch) on Marek's website.
I'm having trouble finding the Faq that you spoke of...

I found the bdcff link, but not the Faq...unless that is what you meant?
http://www.gratissaugen.de/erbsen/bdcff.html

cheers,
Paul
subotai
Member
Posts: 251
Joined: Sun Jan 25, 2009 4:19 pm

Post by subotai »

Here is the direct link:
http://www.gratissaugen.de/erbsen/BD-Inside-FAQ.html

The InsideFaq is about a raw memory dump, not about the BDCFF.
User avatar
paul_nicholls
Member
Posts: 108
Joined: Sun Dec 12, 2010 6:16 am
Location: Tasmania, Australia

Post by paul_nicholls »

subotai wrote:Here is the direct link:
http://www.gratissaugen.de/erbsen/BD-Inside-FAQ.html

The InsideFaq is about a raw memory dump, not about the BDCFF.
Thanks! interesting stuff there :)

cheers,
Paul
subotai
Member
Posts: 251
Joined: Sun Jan 25, 2009 4:19 pm

Post by subotai »

Hey paul,

I hope that it works now. I still have a hint for you concerning the drawing routines. It is better, not to use x y values to set the elements. Instead, you should work with a one dimensional array:

Code: Select all

array[0..879] of byte
Well, in most cases, your drawing routine should work however.

Here is an example for drawing a line:

Code: Select all

//For bd1-engine
Function Draw_Line(Element:Byte; X,Y:Byte; Len, Direction:Byte):Boolean;
Var Counter,i:Integer;
    Valx:Integer;
Begin
Result:=False;

IF Len>128 then Exit; //negative value => no drawing
IF Direction>8 then Exit;

Case Direction of
0: ValX:=-40;  //N
1: ValX:=-39;  //NO
2: ValX:=+1;   //O
3: ValX:=+41;  //SO
4: ValX:=+40;  //S
5: ValX:=+39;  //SW
6: ValX:=-1;   //W
7: ValX:=-41;  //NW
8: ValX:=+160; //Raster drawing
End;

Counter:=(y-2)*40+x;
IF (Counter<0) OR (Counter>879) then Exit;

For i:=1 to Len do
    BEGIN
    Map[Counter]:=Element;
    Counter:=Counter+ValX;
    IF (Counter<0) OR (Counter>879) then Break;
    END;
Result:=True;
End;
User avatar
paul_nicholls
Member
Posts: 108
Joined: Sun Dec 12, 2010 6:16 am
Location: Tasmania, Australia

Post by paul_nicholls »

Thanks for that :)

I hadn't actually tried fixing my boulder dash parsing routines yet...I am debugging my game engine just a little bit more with getting gamepad/joystick support added and not crashing :)

Once I have finished this I will then get back to parsing BD caves again.

Thanks!

cheers,
Paul
Post Reply