commit b5a10f1a8efb303071203b4e34b6602478c6c253
parent 59b072e40cfdca71d55603d734d81fbbee61d3be
Author: Luxferre <lux@ferre>
Date: Tue, 16 Jan 2024 23:12:38 +0200
Supermove functionality finally here, still in testing
Diffstat:
M | nnfc.awk | | | 86 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------- |
1 file changed, 68 insertions(+), 18 deletions(-)
diff --git a/nnfc.awk b/nnfc.awk
@@ -5,8 +5,10 @@
# - 0 is foundation (can be omitted)
# - 1 to 8 are column numbers
# - a, b, c, d are freecell numbers
+# bulk move/supermove operation between columns: [number][number] [number]
+# the first two numbers _must_ only be column numbers (1 to 8)
+# the second (space separated) number is how many top cards we move
# SEED variable can be used to init games M$-style
-# no supermove support for now, need to move cards one at a time
# created by Luxferre in 2024, released into public domain
# Helper functions
@@ -85,7 +87,7 @@ function render(i, j, res) {
# main logic/move function (also handles the undo)
# statuses: 0 - invalid move, 1 - continue, 2 - victory
-function domove(cmd, valid, nums, from, to, si) {
+function domove(cmd, valid, cvalid, nums, ngrp, from, to, amt, i, si, ec, efc) {
if(cmd == "u") { # undo logic
if(undoidx > 0) {
undoidx--
@@ -97,10 +99,14 @@ function domove(cmd, valid, nums, from, to, si) {
return 1 # continue
}
valid = 0 # invalid by default until all checks are done
- # if cmd is not q, h, ah or u, then it must be two numbers
- split(cmd, nums, "") # numbers must be space-separated
+ # if cmd is not q, h, ah or u, then it must be one or two "numbers"
+ split(cmd, ngrp, " ") # parse the command as a whole
+ split(ngrp[1], nums, "") # parse the first part
from = nums[1] # location from which we're moving
to = nums[2] # location to which we're moving
+ amt = int(ngrp[2]) # get the amount of cards being moved
+ if(amt < 1) amt = 1 # it should be at least 1
+ if(amt > 20) amt = 20 # and at most 20
# identify free cells
if(from == "a") from = 9
if(from == "b") from = 10
@@ -114,6 +120,34 @@ function domove(cmd, valid, nums, from, to, si) {
to = int(to)
rfrom = from - 1 # real from location
rto = to - 1 # real to location
+ if(amt > 1) { # constraints for moving a stack of cards
+ cvalid = 0 # it uses its own validation flag
+ if(from > 0 && from < 9 && to > 0 && to < 9) { # both must be columns
+ efc = 0 # count empty freecells here
+ ec = 0 # count empty columns and final result here
+ for(i=0;i<4;i++) if(fcell[i] == -1) efc++
+ for(i=0;i<8;i++) if(tablens[i] == 0) ec++
+ # now, calculate the max card amount to move
+ ec = (2^ec) * (efc + 1) # base formula
+ if(tablens[rto] == 0) ec /= 2 # halve if moving to an empty column
+ if(amt <= ec) { # amount constraint is satisfied, now check the stack
+ efc = tablens[rfrom] - amt # reuse for starting index in source tableau
+ ec = 1 # reuse for successful stack arrangement flag
+ for(i=0;i<amt-1;i++) {
+ si = table[rfrom,efc+i] # the current value
+ cval = table[rfrom,efc+i+1] # the next value
+ if(cval == "") break # we're out of bounds
+ if(!(getcolor(cval) != getcolor(si) && (cval%13) == (si%13) - 1)) {
+ ec = 0
+ break
+ }
+ }
+ if(ec == 1) cvalid = 1 # only then the move is valid
+ }
+ }
+ # in any other case, the move is directly invalid
+ if(cvalid == 0) return 0
+ }
if(from > 0 && from < 13 && to > -1 && to < 13) { # first check
# determine what card we're trying to move
cval = -1
@@ -133,22 +167,33 @@ function domove(cmd, valid, nums, from, to, si) {
valid = 1 # mark the move as valid
}
} else if(to < 9) { # moving to a tableau
- si = table[rto,tablens[rto]-1] # target value
- if((getcolor(cval) != getcolor(si) && (cval%13) == (si%13) - 1) || si == "") {
- table[rto,tablens[rto]] = cval # copy the card there
- tablens[rto]++ # increase tableau length
- if(from < 9) { # moving from a tableau
- delete table[rfrom,tablens[rfrom]-1] # delete the card
- tablens[rfrom]-- # decrease tableau length
- } else fcell[from - 9] = -1 # moving from a free cell
- valid = 1 # mark the move as valid
+ efc = 0 # reuse for starting index in source tableau
+ if(from < 9) efc = tablens[rfrom] - amt
+ if(efc > -1) { # check if we aren't moving more cards than allowed
+ for(i=0;i<amt;i++) { # move the cards as usual
+ if(from < 9) { # re-read the source value if looping over a column
+ cval = table[rfrom, efc+i]
+ if(cval == "") break # we try to read more than is available
+ else cval = int(cval)
+ }
+ si = table[rto,tablens[rto]-1] # target value
+ if((getcolor(cval) != getcolor(si) && (cval%13) == (si%13) - 1) || si == "") {
+ table[rto,tablens[rto]] = cval # copy the card there
+ tablens[rto]++ # increase tableau length
+ if(from < 9) { # moving from a tableau
+ delete table[rfrom,efc+i] # delete the card
+ tablens[rfrom]-- # decrease tableau length
+ } else fcell[from - 9] = -1 # moving from a free cell
+ valid = 1 # mark the move as valid
+ } else break
+ }
}
} else if(fcell[to - 9] == -1) { # moving to a free cell
fcell[to - 9] = cval
if(from < 9) { # moving from a tableau
delete table[rfrom,tablens[rfrom]-1] # delete the card
tablens[rfrom]-- # decrease tableau length
- } else fcell[rfrom - 9] = -1 # moving from a free cell
+ } else fcell[from - 9] = -1 # moving from a free cell
valid = 1 # mark the move as valid
}
}
@@ -193,23 +238,28 @@ function autohome(chres, lres, i) {
function help() {
print "nnfc: no-nonsense FreeCell in POSIX AWK"
+ print "Created by Luxferre in 2024, released into public domain"
print "Script parameters:"
- print "-v ASCII=1\tuse ASCII instead of Unicode suit chars"
- print "-v MONOCHROME=1\t don't use colors"
+ print "-v ASCII=1\tuse ASCII instead of Unicode suits"
+ print "-v MONOCHROME=1\tdon't use colors"
print "-v SEED=xxxxx\tset game seed number (M$-compatible)"
- print "-v NAH=1\tdisable autohoming after every move (use ah command for this)"
+ print "-v NAH=1\tdisable autohoming after every move (use ah for this)"
print "Commands: q - quit, u - undo, ah - autohome, h - this help"
print "Moves: [digit][digit], where \"digits\" are:"
print "- 0 is foundation (can be omitted)"
print "- 1 to 8 are column (tableau) numbers"
print "- a, b, c, d are freecell IDs"
+ print "Supermoves between columns: [digit][digit] [number]"
+ print "The first two digits must only be column numbers (1 to 8)"
+ print "The space-separated number is how many top cards we move"
print "Examples:"
print "7a\tmove from column 7 to freecell a"
print "63\tmove from column 6 to column 3"
print "d1\tmove from freecell d to column 1"
print "4\tmove from column 4 to the foundation"
print "c\tmove from freecell c to the foundation"
- print "ah\tautomatically move all eligible cards to the foundation"
+ print "25 3\tmove top 3 cards from column 2 to column 5"
+ print "ah\tmove all eligible cards to the foundation"
return 1 # continue
}