{迷路です。ゴールすると、ゴールの位置が反対側になって迷路が再構築されるため、無限に遊べます。} {スペースキーを押すと、表示範囲が変わります。} {ある程度小さいサイズの方がおすすめです。} const W: int :: 16 const H: int :: 12 const px: float :: 10.0 const WW: int :: (2 * @W + 1) * @px $ int const WH: int :: (2 * @H + 1) * @px $ int var drawAreaFuncs: []@DrawAreaFuncs func main() do @map :: #[2 * @H + 1, 2 * @W + 1]bool do @userX :: 1 do @userY :: 1 do @createMaze() var wndMain: wnd@Wnd :: wnd@makeWnd(null, %aspect, @WW, @WH, "無限に遊べる迷路です") var drawMain: wnd@Draw :: wnd@makeDraw(wndMain, 0, 0, @WW, @WH, %scale, %scale, false) do @initDrawAreaFuncs() while(wnd@act()) do @moveUser() do @drawMaze() do @drawGoal() do @drawUser() do draw@render(60) if(@userX = @goalX & @userY = @goalY) do @createMaze() end if end while end func var map: [][]bool var aisle: [][]bit8 var x: int var y: int var userX: int var userY: int var goalX: int var goalY: int const U: bit8 :: 1b8 const R: bit8 :: 2b8 const D: bit8 :: 4b8 const L: bit8 :: 8b8 func carve() do @aisle :: #[@H, @W]bit8 do @x :: lib@rnd(0, @W - 1) do @y :: lib@rnd(0, @H - 1) while(true) switch(selectDir()) case 0b8 ret case @U do @aisle[@y][@x] :: @aisle[@y][@x].or(@U) do @y :- 1 do @aisle[@y][@x] :: @D.or(@D.shl(4)) case @R do @aisle[@y][@x] :: @aisle[@y][@x].or(@R) do @x :+ 1 do @aisle[@y][@x] :: @L.or(@L.shl(4)) case @D do @aisle[@y][@x] :: @aisle[@y][@x].or(@D) do @y :+ 1 do @aisle[@y][@x] :: @U.or(@U.shl(4)) case @L do @aisle[@y][@x] :: @aisle[@y][@x].or(@L) do @x :- 1 do @aisle[@y][@x] :: @R.or(@R.shl(4)) end switch end while func selectDir(): bit8 while(true) var ds: []bit8 :: [@U, @R, @D, @L] var shuffle: []int :: lib@shuffle(4) for i(0, ^ds - 1) var d: bit8 :: ds[shuffle[i]] if(checkDir(d)) ret d {まだ掘られていない道があったのでそちらに向かいます} end if end for {掘った場所を戻っていきます} switch d(@aisle[@y][@x].shr(4)) case 0b8 ret d {スタート地点まで戻ってきたので穴掘りを終了します} case @U do @y :- 1 case @R do @x :+ 1 case @D do @y :+ 1 case @L do @x :- 1 end switch end while func checkDir(d: bit8): bool switch(d) case @U ret(@y > 0 & @aisle[@y - 1][@x] = 0b8) case @R ret(@x + 1 < @W & @aisle[@y][@x + 1] = 0b8) case @D ret(@y + 1 < @H & @aisle[@y + 1][@x] = 0b8) case @L ret(@x > 0 & @aisle[@y][@x - 1] = 0b8) default ret false end switch end func end func end func func createMaze() do @goalX :: 2 * @W - @userX do @goalY :: 2 * @H - @userY do @carve() for h(0, 2 * @H, 2) for w(0, 2 * @W, 2) do @map[h][w] :: true end for end for for h(0, @H - 1) for w(0, @W - 1) do @map[2 * h + 1][2 * w + 1] :: false do @map[2 * h + 0][2 * w + 1] :: @aisle[h][w].and(@U) = 0b8 do @map[2 * h + 1][2 * w + 2] :: @aisle[h][w].and(@R) = 0b8 do @map[2 * h + 2][2 * w + 1] :: @aisle[h][w].and(@D) = 0b8 do @map[2 * h + 1][2 * w + 0] :: @aisle[h][w].and(@L) = 0b8 end for end for end func func drawMaze() for h(0, 2 * @H) for w(0, 2 * @W) if(@isDrawArea(w, h)) do draw2d@rect(w $ float * @px, h $ float * @px, @px, @px, @map[h][w] ?(0xFF008855, 0xFFFFCCCC)) end if end for end for if(@drawAreaEdge <>& null) do @drawAreaEdge((@userX $ float + 0.5) * @px, (@userY $ float + 0.5) * @px) end if end func func drawUser() do draw2d@circle((@userX $ float + 0.5) * @px, (@userY $ float + 0.5) * @px, @px * 0.5, @px * 0.5, 0xFF0000FF) end func func drawGoal() do draw2d@rect((@goalX $ float - 0.2) * @px, (@goalY $ float - 0.2) * @px, @px * 1.4, @px * 1.4, 0xFFFF0000) end func {アローキー(←↓↑→)で操作します。} func moveUser(): bool if(myPadPress(%up)) if(!@map[@userY - 1][@userX]) do @userY :- 2 ret true end if end if if(myPadPress(%right)) if(!@map[@userY][@userX + 1]) do @userX :+ 2 ret true end if end if if(myPadPress(%down)) if(!@map[@userY + 1][@userX]) do @userY :+ 2 ret true end if end if if(myPadPress(%left)) if(!@map[@userY][@userX - 1]) do @userX :- 2 ret true end if end if if(myPadPress(%a)) do @isDrawAreaFuncId :+ 1 do @isDrawAreaFuncId :% ^@drawAreaFuncs do @isDrawArea :: @drawAreaFuncs[@isDrawAreaFuncId].isDrawArea do @drawAreaEdge :: @drawAreaFuncs[@isDrawAreaFuncId].drawAreaEdge end if ret false func myPadPress(btn: input@PadBtn): bool var n: int :: input@pad(0, btn) ret n = 1 | n >= 10 & n % 4 = 0 end func end func var isDrawAreaFuncId: int var isDrawArea: func<(int, int): bool> var drawAreaEdge: func<(float, float)> class DrawAreaFuncs() +var isDrawArea: func<(int, int): bool> +var drawAreaEdge: func<(float, float)> +func init(a: func<(int, int): bool>, b: func<(float, float)>): @DrawAreaFuncs do me.isDrawArea :: a do me.drawAreaEdge :: b ret me end func end class func initDrawAreaFuncs() do @drawAreaFuncs :: #[0]@DrawAreaFuncs do @drawAreaFuncs :~ [(#@DrawAreaFuncs).init(drawWholeArea, null)] do @drawAreaFuncs :~ [(#@DrawAreaFuncs).init(drawCircleAreaS, drawCircleAreaEdgeS)] do @drawAreaFuncs :~ [(#@DrawAreaFuncs).init(drawCircleAreaM, drawCircleAreaEdgeM)] do @drawAreaFuncs :~ [(#@DrawAreaFuncs).init(drawCircleAreaL, drawCircleAreaEdgeL)] do @drawAreaFuncs :~ [(#@DrawAreaFuncs).init(drawSquareAreaS, null)] do @drawAreaFuncs :~ [(#@DrawAreaFuncs).init(drawSquareAreaM, null)] do @drawAreaFuncs :~ [(#@DrawAreaFuncs).init(drawSquareAreaL, null)] { do @drawAreaFuncs :~ [(#@DrawAreaFuncs).init(drawLadarAreaS, drawLadarAreaEdgeS)] do @drawAreaFuncs :~ [(#@DrawAreaFuncs).init(drawLadarAreaM, drawLadarAreaEdgeM)] do @drawAreaFuncs :~ [(#@DrawAreaFuncs).init(drawLadarAreaL, drawLadarAreaEdgeL)] } var id: int :: 0 ; do id :: ^@drawAreaFuncs - 1 do @isDrawArea :: @drawAreaFuncs[id].isDrawArea do @drawAreaEdge :: @drawAreaFuncs[id].drawAreaEdge func drawWholeArea(w: int, h: int): bool ret true end func func drawCircleAreaSub(w: int, h: int, size: int): bool ret(@userX - w) ^ 2 + (@userY - h) ^ 2 < size end func func drawCircleAreaS(w: int, h: int): bool ret drawCircleAreaSub(w, h, 18) end func func drawCircleAreaM(w: int, h: int): bool ret drawCircleAreaSub(w, h, 30) end func func drawCircleAreaL(w: int, h: int): bool ret drawCircleAreaSub(w, h, 51) end func func drawCircleAreaEdgeSub(w: float, h: float, size: int) do draw2d@circleLine(w, h, size $ float, size $ float, @px * 2 $ float, draw@black) end func func drawCircleAreaEdgeS(w: float, h: float) do drawCircleAreaEdgeSub(w, h, 45) end func func drawCircleAreaEdgeM(w: float, h: float) do drawCircleAreaEdgeSub(w, h, 60) end func func drawCircleAreaEdgeL(w: float, h: float) do drawCircleAreaEdgeSub(w, h, 75) end func func drawSquareAreaSub(w: int, h: int, size: int): bool ret |(@userX / size = w / size | @userX / size = (w - 1) / size) & |(@userY / size = h / size | @userY / size = (h - 1) / size) end func func drawSquareAreaS(w: int, h: int): bool ret drawSquareAreaSub(w, h, 4) end func func drawSquareAreaM(w: int, h: int): bool ret drawSquareAreaSub(w, h, 6) end func func drawSquareAreaL(w: int, h: int): bool ret drawSquareAreaSub(w, h, 8) end func func drawLadarAreaSub(w: int, h: int, ratio: float): bool if(drawCircleAreaSub(w, h, 4)) ret true end if var angle: float :: currentAngle() var posRot: float :: lib@invRot(w $ float, h $ float, @userX $ float, @userY $ float) ret(2.0 * lib@pi + posRot - angle).abs() % (2.0 * lib@pi) < ratio * (2.0 * lib@pi) end func func drawLadarAreaS(w: int, h: int): bool ret drawLadarAreaSub(w, h, 0.125) end func func drawLadarAreaM(w: int, h: int): bool ret drawLadarAreaSub(w, h, 0.25) end func func drawLadarAreaL(w: int, h: int): bool ret drawLadarAreaSub(w, h, 0.5) end func func drawLadarAreaEdgeSub(w: float, h: float, ratio: float) const rMin: float :: @px * 1.7 var rMax: float :: [@W, @H].max() $ float * @px * 3.0 var angle: float :: currentAngle() var x1: float :: rMin * lib@cos(angle) + w $ float var y1: float :: rMin * lib@sin(angle) + h $ float var x2: float :: rMax * lib@cos(angle) + w $ float var y2: float :: rMax * lib@sin(angle) + h $ float do draw2d@line(x1, y1, x2, y2, @px * 1.5, draw@black) do angle :+ ratio * 2.0 * lib@pi do x1 :: rMin * lib@cos(angle) + w $ float do y1 :: rMin * lib@sin(angle) + h $ float do x2 :: rMax * lib@cos(angle) + w $ float do y2 :: rMax * lib@sin(angle) + h $ float do draw2d@line(x1, y1, x2, y2, @px * 1.5, draw@black) end func func drawLadarAreaEdgeS(w: float, h: float) do drawLadarAreaEdgeSub(w, h, 0.125) end func func drawLadarAreaEdgeM(w: float, h: float) do drawLadarAreaEdgeSub(w, h, 0.25) end func func drawLadarAreaEdgeL(w: float, h: float) do drawLadarAreaEdgeSub(w, h, 0.5) end func func currentAngle(): float ret(draw@cnt() $ float * 0.005) % (2.0 * lib@pi) end func end func