Hi, Jack!
I think what you are doing is really cool, and I would love to read the book one day!
06.06.2019, 15:16, "Jack Lucas via Factor-talk" <factor-talk@lists.sourceforge.net>:
Yesterday I was trying to create this adjacency system for one of the games I'm working on. I have no idea if this will stay like this, but, at the time, it sure felt like I was trying to jam first class words into Factor, and I'd like to know if there's a better method.The goal of this snippet of code is to take some originating coordinates on the stack like 40 40 and convert it into the adjacent square coordinates in my grid. So from 40 40 we might get a sequence back like { { 0 0 } { 80 0 } { 0 80 } { 80 80 } } describing the coordinates of squares adjacent ( in the corner going diagonally ). I obviously didn't want to rewrite adjacent 4 times with a different combination of +'s and -'s so I instead wrote it as you see here.
Thinking in terms of sequences and matrices, this is the solution I came up with for you:
: adjacent-diagonals ( pos step -- seq )
{ - + } [ execute( x y -- n ) ] with cartesian-map
first2 cartesian-product concat ;
{ - + } [ execute( x y -- n ) ] with cartesian-map
first2 cartesian-product concat ;
Test code:
IN: scratchpad { 40 40 } 40 adjacent-diagonals .
{ { 0 0 } { 0 80 } { 80 0 } { 80 80 } }
Correspondingly, if the player is facing "left", you could pick the necessary pair of coordinates by doing something like
: left-squares ( square -- seq )
grid-size get adjacent-diagonals { 0 2 } swap nths ;
or, generalizing over the directions,
: player-direction-squares ( -- seq )
{
{ "down" { 0 1 } }
{ "up" { 2 3 } }
{ "left" { 0 2 } }{ "right" { 1 3 } }
} player-sym get direction>> of ;
: adjacent-squares ( pos -- seq )
grid-size get adjacent-diagonals player-direction-squares swap nths ;
What do you think?
Another approach could revolve around the following definition, I think you can figure out the rest of the details:
: player-direction-squares ( -- seq )
{
{ "down" { { + - } { - - } } }
{ "up" { { + + } { - + } } }
{ "left" { { - - } { - + } } }{ "right" { { + - } { + + } } }
} player-sym get direction>> of ;
:: adjacent ( x y ex ex2 -- quot )[ x grid-size get ex execute ,y grid-size get ex2 execute , ] { } make ; inline: upper-left ( x y -- seq )\ - \ - adjacent ;: upper-right ( x y -- seq )\ + \ - adjacent ;: bottom-left ( x y -- seq )\ - \ + adjacent ;: bottom-right ( x y -- seq )\ + \ + adjacent ;! player-sym is just a tuple holding the players state! Whatever direction the player is facing is the side! we want him to be able to grab items from.: player-direction-squares ( -- squares )player-sym get direction>>{{ "left" [ { bottom-left upper-left } ] }{ "right" [ { bottom-right upper-right } ] }} case ;! square-coordinates ( square -- x y ): adjacent-squares ( square -- list )square-coordinates [ rot execute( x y -- seq ) ] 2curryplayer-direction-squaresswap map ; inlineIn this way, depending on which direction the player is facing, finding the adjacent squares is literally a matter of mapping over the words themselves rather than the data. Since it would look like...{ "bottom-left" "upper-left" } [ x y rot execute( x y -- seq ) ] mapThe question for me becomes, is this an over-complicated way of achieving a simple effect? I wonder if there's a way to do it like lisp-macros where I can just syntactically insert the words I want without evaluating them. In any case, I'm mostly posting this to see if I'm going off the deep end of only having a problem because I'm thinking about the issue the wrong way or if this genuinely is the right direction to go in trying to solve a problem like this in Factor. Either way it was fun to try to make without repeating myself 4 times.Copiously Caffeinated,
Sequentially Coordinated,
---=====---
Александр
_______________________________________________ Factor-talk mailing list Factor-talk@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/factor-talk