mailto: blog -at- heyrick -dot- eu

Navi: Previous entry Display calendar Next entry
Switch to desktop version

FYI! Last read at 10:41 on 2024/11/23.

A week in the new order

Chaos.

Well, not chaos. There was work to do, and I had to train some of the others in what I do so they can replace me if I'm away. I think the idea is that we all know each other's jobs so we can mix and match as appropriate.

But for somebody used to having a very definitive schedule, it was chaos.

I was summoned to have a discussion with my boss on Thursday - a week on the flip side of the event horizon.
I get the impression that this all happened above her, and quite likely for exactly the reason I think.

I've asked that other committee members (who are more on my side here) don't agitate anything right now. I am, obviously, somewhat miffed at how it all went down, but it has and that's that. Let's see how this all plays out.

Remember that I believe in the concept of things happening for a reason? I'll be buggered if I know (or can think of) the reason for this change, but like I said, let's see how it goes.

As for the week? I hurt. Doing the industrial washing up is exercising a whole different set of muscles to wiping tables and scrubbing toilets. But this is to be expected. I will, however, have to stop trying to pick up a dozen baking trays at once. It was no big deal when I started here and was 35. I'm less than a year to half a decade of crustiness, and I'm really not up to flexing like that.

 

No, I'm not Vin Diesel

Set off to work this morning. It was -3 and clear, but the clouds in the direction of work had "snow" written all over them.
For most of the journey, there was no problem.

Until I got to the roundabout in the town before work. If you've been watching my videos, it's the one where the van tried to cut in front of me.
I was doing something like 15kph, because I like to go around the roundabout properly rather than driving over it like everybody else.
That's when it became clear that my back end was swinging around faster than the front.

So... in a toy car doing a speed barely faster than a run, I drifted a tiny roundabout.

Feel free to laugh.

I didn't hit anything, and it was over before I had any time to even think about how to respond. The car behind me, however, saw this and slammed on the brakes. And, yeah, that didn't quite go as planned.
He/she didn't hit anything either, but had to reverse and slowly turn to be heading in the right direction.

The road from that roundabout to the big one before the supermarket, maybe a kilometre or so? Total skating rink. I could feel the car shuddering as the wheels made and unmade contact. As it was a straight line, we (myself and the car behind) did it at about 25. It was a 50 zone.

As I came to the big roundabout, a jam sandwich went whizzing by, blues flashing but no siren. I'm guessing somebody had a worse morning than the two of us.

It's supposed to be subzero in the morning until Wednesday, but there's no rain forecast so hopefully the moments of sun will keep things dry so there's no more ice.
Then it's supposed to be a high of 14 for two days, which seems like either an anomaly or an apology.

 

Parcels

Well, my CD from Canada was supposed to have arrived on Tuesday.
Instead, I got a letter in the mail saying that I had to pay import duty of €11 - on a CD costing €3 with around €12 postage.

I wasn't going to be around to deal with this, so I went to the La Poste website, and elected to pay the import duties on-line.

€5.

This was broken down as €3 for the actual import duty (20% of the cost of the item plus shipping, rounded up to a whole euro amount), plus a fee of €2 for "handling".

First of all, what the actual hell are they doing applying tax to the shipping charge?

But secondly, and more importantly, why did my post person quote me €11? The website itself made it quite clear that by paying on-line, I would economise €6. And I did.
But, wait, this amount is set by and paid to the government. It's import duty, with a small handling charge added on top. So what justifies trying to charge more than double if I don't do it on-line?

The rule is clear. If the postperson comes along with a parcel with import duty, to say no - keep it, I'll pay the duty on-line, you can bring it out in a couple of days.

Which is absolutely ridiculous.

Anyway, nothing came on Wednesday. I left a message for the postie to say that the tax had been paid. She left me a message to say she had spoken to her boss and she thinks I made an error as it was for €11, not €5, and as such the duty hasn't been marked as paid.
As it turns out, the duty was marked as unpaid because it took until 1pm the following day for it to be processed. What, is it done by hand?

My postie left her mobile number, so I sent a few text messages for a discussion that was increasingly surreal. Eventually I took a photo of the note that had the phone number and sent that by MMS.
The reply... I was speaking to somebody completely different at the other end of the country. My postie had written her number down incorrectly.
I apologised profusely, and the woman I was talking to said she hopes I get it sorted - import duty is a nightmare.

I wasn't expecting it on Thursday. I mean, everybody was on strike, right?

It arrived Thursday.

Bunny ears
Bunny ears.

 

I had ordered something else, from the UK this time. There was no import duty as the item had already been taxed and it was a reciprocal agreement, which I guess Canada doesn't have.

It left somewhere near Leeds, went to Hinkley (as in, the nuclear reactor in Somerset?), then to Paris, then to Rennes, and finally out to me. It took three days. Pretty impressed by the speed of that.
Anyway, I went to the track and trace and it said that my only options were to have it delivered or to pick it up from the depot in Rennes. I couldn't ask for it to be left at my local supermarket.

I ticked a box to give permission for the parcel to be left, and to be left without signature and that I'd accept the risk of that.

The driver allegedly passed, discovered I wasn't home, and didn't deliver the parcel as I was absent.

Thankfully he didn't take it back to the depot. He left it at a supermarket in a town twenty miles away. The place it was left is, actually, our "sub-head" town because... it's complicated and the French are very territorial. But it's bloody annoying because if I look to have Amazon leave anything at a pickup point, they suggest this place because of how French administration works, and don't ever offer to leave parcels in the closer town where I work because... FFS.

Anyway, there would be a receipt. I say allegedly because I went home to pick up the little slip that was left in the letterbox... except there was no slip. So I'm not sure whether the driver even bothered to turn up, or just looked at the long driveway and thought "sod this" and marked me as being absent.

I went to the supermarket anyway (a journey twice as long as cutting across directly from work) and handed over my (French) ID card. Well, Residency Permit. It had my name, address, and an up to date photo to demonstrate that the government attests that the lifeform standing in front of the person is supposed to be wandering around.
Thankfully the person at the service desk looked it up by address and went and fetched it. Nothing to sign, only scan the code and call it delivered.

So the rule is clear. Just don't order stuff from overseas.
Which, knowing how protectionist the government can be, is probably exactly the intended idea. Pffft.

 

The Met

So a Met officer raped a bunch of women, not to mention stripping one woman and imprisoning her in a tiny cupboard under the stairs.
Actually, that's badly understating it.

With a known count of 48 rapes, he's one of the worst sex offenders in modern British history. All the more egregious that he was a serving officer of the Met, which led others (police and prosecutors) to tell the woman that claims like this against a police officer wouldn't be believed. Especially as he threatened to plant drugs in one person's car, with a "who are they going to believe?" question.

He's going to be sentenced, and may well go behind bars for a long time. Really, six foot deep is where he belongs.
However the continual rancid stories about the Met suggests that perhaps the best idea is to disband it completely and rebuild it from the beginning with an entirely new workforce taken from around the country. Former Met officers can move to other police positions, and hopefully it'll break up any comraderie as well as shaking out the bad people (of which there may be over a thousand).
There is something horribly broken within the Met, and it looks like either Cressida Dick was complicit or sleepwalking through the job.

Either way, when an entire gender has justifiable reason to fear the police, pathetic platitudes won't cut it. Time to rip and retry.

 

Ray casting 2

A little gift for the weekend.

I gave you code for rotating the vectors to any arbitrary angle. So it wasn't hard to plug this into the program to actually do this according to the keys pressed, which provides rotation. We move 0.05 radians, which is about 2.8°.
Then to check the location of a map reference with an offset added, and if it's an empty tile, to do the move. This provides forward and backward movement.

There is no attempt at throttling or maintaining a steady rate of movement. It's just the bare bones to have a map that you can actually move around in.

Five versions of the program are provided in the archive. Listed in order of effective speed (as I wandered around the map):

NameFPSWhat it is
raycast2 18-19 The original source with comments.
raycast2nc 19-23 The original source with no comments.
raycast2cr 25-34 Crunched source.
raycast2fpa 25-35 Compiled with ABC† set to use FPA maths.
raycast2vfp 35-65 Compiled with ABC† set to use VFP maths.

† - built from a source that uses ColourTrans_SetGCOL to set the colours as ABC still doesn't support the GCOL r,g,b form.

Now, all you're missing is the programs (Zip, 16,442 bytes).

 

I'm just going to dump the entire commented source here. The changes are described, and shouldn't be too hard to work out. Though, I would imagine this might just be a step too far for a BBC Master version. ☺

REM >raycast2
REM
REM Rick's simple ray-caster, version 2
REM   * Added movement (rotation and foreward/backward)
REM
REM https://heyrick.eu/blog/index.php?diary=20230120
REM
REM Basic demonstration of principle
REM
REM The principle is as described by Lode Vandevenne at
REM https://lodev.org/cgtutor/raycasting.html
REM
REM What's worth noting here is that we do *NOT*
REM work in degrees like a normal ray-caster, so
REM the code that follows is rather more compact
REM than you may see in other places, but it does
REM require competent floating point maths support.
REM

ON ERROR PROCerror

REM 640x480 in 256 colours; it's VGA so
REM everything ought to support this.
MODE 28

REM The physical size of the screen
width% = 640
height% = 480

REM Set up triple buffering
SYS "XOS_ReadModeVariable", -1, 7 TO ,, scrsize%
scrwant% = scrsize% * 3
SYS "XOS_ReadDynamicArea", 2 TO , scrcurr%
screxpa% = scrwant% - scrcurr% : REM How much to enlarge by
IF ( screxpa% > 0 ) THEN
  SYS "XOS_ChangeDynamicArea", 2, screxpa% TO ; f%
  IF (f% AND 1) THEN ERROR 123, "Not enough screen memory"
ENDIF

REM Set up other screen stuff
SYS "Hourglass_Smash"
MOUSE OFF
SYS "OS_RemoveCursors"
SYS "OS_Byte", 114, 0 : REM Shadow modes
bank% = 1
PROCswitchbank


REM The size of the 2D map
REM Let's keep it simple for now
mapx% = 16
mapy% = 8
DIM map%(mapx%, mapy%)
FOR loopy% = 7 TO 0 STEP -1
  FOR loopx% = 0 TO 15
    READ map%(loopx%, loopy%)
  NEXT
NEXT

REM 0 = Empty
REM 1 = Red square
REM 2 = Green square
REM 3 = Blue square
DATA 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
DATA 1,0,0,0,3,3,0,0,0,0,0,0,0,0,0,1
DATA 1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1
DATA 1,0,0,0,3,0,0,0,1,0,2,0,0,0,0,1
DATA 1,0,3,0,0,0,3,0,1,0,0,0,0,0,0,1
DATA 1,0,0,0,2,0,0,0,0,0,3,0,0,0,0,1
DATA 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
DATA 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
REM                             /|\
REM                              |
REM Viewer is here, fourth row up. looking to the LEFT.

REM Note that as of now, it's lots of floating point maths


REM Where in the map does the viewer start?
ourx = 14
oury = 4

REM Looking to the left
xdir = -1
ydir = 0

REM The projection plane, in 2D
REM This MUST be perpendicular to the direction.
xproj = 0
yproj = 0.65


REM yproj being 0.65 above corresponds to a field of view of
REM about 65 degrees, which is a good value for a old style
REM squarish screen, such as the VGA mode used here.
REM If using a 16:9 display, you'll need a wider field of view
REM because of the extra width. Try 0.85 which equals a field of
REM view of about 80 degrees.
REM
REM To convert the above value into degrees for a viewing angle:
REM   value = 0.65
REM   PRINT ((ATN(value / 1) * 2) / PI) * 180
REM (this converts the value into radians, and then into degrees)
REM


REM A loop to repeatedly draw according to defined location and angle
timeout% = TIME + 100
fcnt% = 0
fps% = 0
WHILE TRUE
  PROCswitchbank
  CLS

  REM Draw the floor
  GCOL 48, 48, 48  : REM Dark grey
  RECTANGLE FILL 0, 0, (width% << 1), height%

  REM And now the ceiling
  GCOL 98, 98, 98 : REM Lighter grey
  RECTANGLE FILL 0, height%, (width% << 1), height%


  REM Now, cast rays for each scrcol across the screen, starting from the left.

  FOR scrcol% = 0 TO (width% - 1)

    REM Let's do the easy inits first.

    REM For now, let's look to see what map location we are in.
    mapx% = ourx
    mapy% = oury
    REM We use an integer here in order to lose the fractional part,
    REM as in this case we don't care how far along in any position
    REM the viewer is, only which block matches where the viewer is.

    REM These two values represent the distance from our current
    REM (exact) location to the next square boundary. This is
    REM updated as we step along.
    xedge = 0
    yedge = 0

    REM The step values are -1 if it's a negative step, or 1 if it's a
    REM positive step. Initially zero as the stepping hasn't been set up.
    xstep% = 0
    ystep% = 0

    REM Has a wall been hit?
    wallhit% = FALSE

    REM Which side was hit? FALSE for an X side, TRUE for a Y side
    side% = 0

    REM This will be the distance to the actual wall that we're going
    REM to draw on the screen.
    towall = 0


    REM Now for the freaky maths

    REM Calculate our angle offset for the desired screen column.
    REM This goes from -1 on the left, to 0 in the middle, to 1 on the right.
    angle = (2.0 * (scrcol% / width%)) - 1

    REM Now set up two rays. Remember when we are talking about X and Y
    REM we are talking about the GRID that represents the array that our
    REM map is in. It isn't X,Y on the screen, or in some 3D space, it
    REM is the imaginary X,Y divisions between array elements.
    REM Or, to put it more simply, imagine that you have written the
    REM contents map% on a piece of squared paper like you used in maths
    REM class. The horizontal lines are your X positions, and the vertical
    REM lines are your Y positions.
    xray = xdir + (xproj * angle)
    yray = ydir + (yproj * angle)

    REM Now we work out how far we must step from one square edge to
    REM the next. Since the rays travel in a straight line, we only
    REM need to calculate this once.
    IF (xray <> 0) THEN xdelta = ABS(1 / xray) ELSE xdelta = 12345678
    IF (yray <> 0) THEN ydelta = ABS(1 / yray) ELSE ydelta = 12345678

    REM To explain the above a little better, the actual calculation
    REM would be:
    REM   xdelta = SQR(1 + (yray * yray) / (xray * xray))
    REM but because we already did some of this calculation when sorting
    REM out xray/Y above, and we're only interested in the RATIO
    REM between the X and the Y, all of this can be simplified down to
    REM simply dividing 1 by the ray distance.


    REM Now we work out which stepping to use, and our initial distance
    REM to the edge of the current square.
    IF ( xray < 0 ) THEN
      REM We're moving leftwards in the map
      xstep% = -1
      xdist = ( ourx - mapx% ) * xdelta
    ELSE
      REM We're moving rightwards in the map
      xstep% = 1
      xdist = ( (mapx% + 1) - ourx ) * xdelta
    ENDIF

    IF ( yray < 0 ) THEN
      REM We're moving downwards in the map
      ystep% = -1
      ydist = ( oury - mapy% ) * ydelta
    ELSE
      REM We're moving upwards in the map
      ystep% = 1
      ydist = ( (mapy% + 1) - oury ) * ydelta
    ENDIF

    REM Now look for a wall
    WHILE ( wallhit% = FALSE )
      IF ( xdist < ydist ) THEN
        REM The next X boundary is closer, so let's step to it
        mapx% += xstep%
        xdist += xdelta
        side% = FALSE
      ELSE
        REM The next Y boundary is closer, so let's step to it
        mapy% += ystep%
        ydist += ydelta
        side% = TRUE
      ENDIF

      REM Was something hit?
      IF ( map%(mapx%, mapy%) <> 0 ) THEN wallhit% = TRUE
    ENDWHILE


    REM Do you see how the two rays worked here? They are both
    REM being cast together at the same time, and we're simply
    REM stepping to look at whichever happens to be the closest.

    REM Now that we know that something has been hit, we can work
    REM out the wall distance. This is easy, we simply subtract the
    REM delta that we stepped over from the accumulated distance to
    REM the next side.
    IF side% = FALSE THEN
      REM It's an X boundary
      towall = xdist - xdelta
    ELSE
      REM It's a Y boundary
      towall = ydist - ydelta
    ENDIF
    IF (towall = 0) THEN towall = 1


    REM Now we have the wall distance, work out how big this line should be
    drawsize% = height% / towall

    REM Now work out the lowest and highest pixel to actually draw on
    REM the screen; clipping it if it goes off the screen.
    drawbot% = (-drawsize% / 2) + (height% / 2)
    IF ( drawbot% < 0 ) THEN drawbot% = 0

    drawtop%   = ( drawsize% / 2) + (height% / 2)
    IF ( drawtop% >= height% ) THEN drawtop% = ( height% - 1)


    REM Now work out what colours we want
    col% = 127
    IF (side% = FALSE) THEN col% += 128
    CASE map%(mapx%, mapy%) OF
      WHEN 1 : GCOL col%, 0, 0 : REM Red
      WHEN 2 : GCOL 0, col%, 0 : REM Green
      WHEN 3 : GCOL 0, 0, col% : REM Blue
    ENDCASE


    REM And, finally, draw the line, with correction between
    REM OS units and pixels for MODE 28.
    MOVE (scrcol% << 1), (drawbot% << 1)
    DRAW (scrcol% << 1), (drawtop% << 1)

  NEXT


  REM FPS tracking
  fcnt% += 1
  IF ( TIME >= timeout% ) THEN
    timeout% = TIME + 100
    fps% = fcnt%
    fcnt% = 0
  ENDIF


  REM A screen has been drawn, so now handle keypresses
  REM   Esc  . . . . . . . Quit ;)
  REM   Left / Right . . . Rotate
  REM   Up . . . . . . . . Forwards
  REM   Down . . . . . . . Backwards
  REM   F  . . . . . . . . Show FPS
  REM   S  . . . . . . . . Screenshot


  REM LEFT or RIGHT
  IF ( FNkey(25) ) OR ( FNkey(121) ) THEN
    IF FNkey(25) THEN rot = 0.05 ELSE rot = -0.05
    oldx = xdir
    xdir = (xdir * COS(rot)) - (ydir * SIN(rot))
    ydir = (oldx * SIN(rot)) + (ydir * COS(rot))

    oldx = xproj
    xproj = (xproj * COS(rot)) - (yproj * SIN(rot))
    yproj = (oldx * SIN(rot)) + (yproj * COS(rot))
  ENDIF

  REM UP
  IF ( FNkey(57) ) THEN
    IF ( map%(ourx + (xdir * 0.1), oury) = 0 ) THEN ourx += xdir * 0.1
    IF ( map%(ourx, oury + (ydir * 0.1)) = 0 ) THEN oury += ydir * 0.1
  ENDIF

  REM Down
  IF ( FNkey(41) ) THEN
    IF ( map%(ourx - (xdir * 0.1), oury) = 0 ) THEN ourx -= xdir * 0.1
    IF ( map%(ourx, oury - (ydir * 0.1)) = 0 ) THEN oury -= ydir * 0.1
  ENDIF

  REM F(PS)
  IF ( FNkey(67) ) THEN
    PRINTTAB(0,0);STR$(fps%)+" fps"
  ENDIF

  REM S for a Screenshot
  IF ( FNkey(81) ) THEN
    OSCLI("ScreenSave $._3dscene"+MID$(TIME$,17,2)+MID$(TIME$,20,2)+MID$(TIME$,23,2))
  ENDIF

ENDWHILE

END

:

DEFPROCerror
  REM If we abort with shadow modes set up, RISC OS will poop its nappy
  REM So this restores the screen state back to what it was on entry
  VDU 4
  PROCdrawbank(0)
  PROCshowbank(0)
  SYS "OS_Byte", 114, 1 : REM Non-shadow
  SYS "ColourTrans_SetTextColour", &00000000, (1<<7) : REM Background
  SYS "ColourTrans_SetTextColour", &FFFFFF00, 0      : REM Foreground
  PRINTTAB(0,0);REPORT$+" at "+STR$(ERL)
  END
ENDPROC

:

DEFPROCdrawbank(w%)
  REM What screen bank are we drawing to?
  SYS "XOS_Byte", 112, w%
ENDPROC

:

DEFPROCshowbank(w%)
  REM What screen bank is the user looking at?
  SYS "XOS_Byte", 113, w%
ENDPROC

:

DEFPROCswitchbank
  REM Furtle with the screen banks
  WAIT
  PROCshowbank(bank%)
  bank% = (bank% MOD 3) + 1
  PROCdrawbank(bank%)
ENDPROC

:

DEFFNkey(k%)
  REM Returns TRUE if the nominated key is pressed, else FALSE
  SYS "OS_Byte", 121, (k% EOR &80) TO , r%
  IF r% = &FF THEN =TRUE
=FALSE

 

Have fun!

By the way - If you're trying this and wondering why it suddenly speeds up when there are lots of boxes on-screen (which is sort of the opposite to what you'd expect), fridge brilliance is that it's because there's actually less needing to step through the rays before we register a hit, so the code is doing less work the more boxes are on screen.

 

 

Your comments:

No comments yet...

Add a comment (v0.11) [help?]
Your name:

 
Your email (optional):

 
Validation:
Please type 37960 backwards.

 
Your comment:

 

Navi: Previous entry Display calendar Next entry
Switch to desktop version

Search:

See the rest of HeyRick :-)