Arc/logic.bqn

70 lines
4.0 KiB
BQN
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env BQN
# SPDX-License-Identifier: AGPL-3.0-or-later
# SPDX-FileCopyrightText: 2023 Rampoina <rampoina@protonmail.com>
Game{
𝕊 levelPathcharscolors:
moves00 # list of moves, each move is a direction, we start without moving
floor,player,box,machine,pmachine,wall,lmirror,rmirror,hbeam,vbeam,xbeam,llaser,rlaser,ulaser,dlaserchars
beamshbeamvbeamxbeam
mirrorslmirrorrmirror
lasersllaserrlaserulaserdlaser
movablesplayerboxmirrors # player, box and mirrors
opaqueplayerboxmachinewalllasers # non laser reflecting
emptiesfloorbeams # floor and laser beams
cols(chars)<(colors) # start with all glyphs being the default color
cols (1colors)˙(pmachine)
cols (2colors)¨(mirrors)
cols (3colors)¨(beams)
Colorize{𝕩˜cols˜chars𝕩} # 𝕩: character | Turn character into color+character
lTiles{𝕩movables ? 𝕩floor; 𝕩}¨chars # list of all the possible tiles as lists of numbers
# Turns the level from ascii strings into a 2d matrix of lists
Ascii2Matrix{(chars𝕩)lTiles}¨(˝·¬2+)
# 𝕨 Tiles 𝕩 | 𝕩: object coordinate (3‿1) | 𝕨: direction vector (¯1‿0)
# result: ⟨ ⟨ 3 1 ⟩ ⟨ 2 1 ⟩ ⟨ 1 1 ⟩ ⟩
# returns 3 tiles in the specified direction from the
Tiles{𝕩,𝕩+𝕨,𝕩+2×𝕨} # given object (including itself)
# Move 𝕩 | 𝕩: ⟨⟨1,0⟩,⟨0⟩⟩ (2 tiles) | result: ⟨⟨0⟩,⟨1,0⟩⟩
# Move the first object in the first tile to the second tile.
# Only move Movable tile -> Empty tile
# the second tile can't be a movable object because we moved it previously
# if it is it means that the object was unmovable (next to a wall) so we do nothing
Move{ab:1a,(a)b}{´(movablesempties)<¨𝕩}
# Push 𝕩 | 𝕩: ⟨⟨1,0⟩,⟨2,0⟩,⟨0,0)⟩ (3 tiles) | result: ⟨⟨0⟩,⟨1,0⟩,⟨2,0)⟩
# Given 3 tiles try to [P]ush the second tile (possible box)
# and afterwards try to move the first one (player) if possible
PushMove(2)Move(1)
FindIdx/()
# w‿d Bounce x | x: map | w‿d: w: current position, d: direction of the laser
# Calculates the bounces of a laser beam recursively
Bounce{(wd)S x:{
opaque˜wx?(machine=wx)x,pmachine˙(w)x@; # laser hits a non-mirror
empties˜wx ? # Empty space
w+d,dS{((×d)hbeamhbeamxbeamxbeam,vbeamxbeamvbeamxbeam)˜floorhbeamvbeamxbeam𝕩}(w)x; # Draw laser and recurse
# laser hits a mirror
dd×-¬lmirror=wx # calculate the mirror bounce direction
w+d,dS x } # recurse to the next position
}
# Shoot 𝕩 | 𝕩: map | calculates the bounces for each laser
Shoot{𝕩 {𝕨Bounce´𝕩} <0¯1,<01,<¯10,<10(˜¨+)¨ FindIdx(¨𝕩)¨ lasers}
Step{Push((𝕨 Tiles player FindIdx ¨𝕩))𝕩} # 𝕨 S 𝕩 | 𝕨: direction | 𝕩:level | Step the game
DrawLevel{´¨<˘Colorize¨chars˜+´¨Shoot 𝕨 Step´ 𝕩} # 𝕨 Draw 𝕩 | 𝕨: levels | 𝕩: moves | Draw the game in ASCII
Win{¬´˝machine=¨Shoot 𝕩}# W 𝕩 | 𝕩: level | [W]in condition, no unpowered machines after shooting laser
Next{movesmoves<𝕩}
Undo{𝕊:moves(-1<)moves}
Draw{𝕊:•Out¨ (currentLevellevels) DrawLevel moves}
WinLevel{𝕊:Win(currentLevellevels)Step´moves}
Reset{𝕊:moves00}
NextLevel{𝕊:currentLevelcurrentLevel+1Reset @}
Over{𝕊:currentLevel<levels}
SplitOnEmpty{𝕩˜(-˜+`׬)0=¨𝕩}
levelsAscii2Matrix¨>¨SplitOnEmpty•FLines levelPath # Load file containing levels
currentLevel0
}