Skip to content

Commit 64ce635

Browse files
committed
modified: Game solvers/asciiplanes-player.sf -- prefer moves near the center of the board
1 parent 37356f3 commit 64ce635

File tree

2 files changed

+38
-46
lines changed

2 files changed

+38
-46
lines changed

Game solvers/asciiplanes-player.sf

+34-41
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ main:
5555
--size=i : length side of the board (default: #{BOARD_SIZE})
5656
--planes=i : the total number of planes (default: #{PLANES_NUM})
5757
--wrap! : wrap the plane around the play board (default: #{wrap_plane})
58+
--head=s : character used for the head of the plane (default: "#{head_char}")
5859
--hit=s : character used when a plane is hit (default: "#{hit_char}")
5960
--miss=s : character used when a plane is missed (default: "#{miss_char}")
6061
--colors! : use ANSI colors (requires Term::ANSIColor) (default: #{use_colors})
@@ -79,15 +80,15 @@ func ver {
7980
}
8081

8182
if (ARGV) {
82-
var getopt = (
83-
try { frequire('Getopt::Long') }
84-
catch { STDERR.print("Can't load the 'Getopt::Long' Perl module...\n"); Sys.exit(2) }
85-
)
83+
var getopt =
84+
try { frequire('Getopt::Long') }
85+
catch { STDERR.print("Can't load the 'Getopt::Long' Perl module...\n"); Sys.exit(2) }
8686

8787
getopt.GetOptions(
8888
'board-size|size=i' => func(_,v) { BOARD_SIZE = Num(v) },
8989
'planes-num=i' => func(_,v) { PLANES_NUM = Num(v) },
9090
'seed=i' => func(_,v) { seed = Num(v) },
91+
'head-char=s' => func(_,v) { head_char = Str(v) },
9192
'hit-char=s' => func(_,v) { hit_char = Str(v) },
9293
'miss-char=s' => func(_,v) { miss_char = Str(v) },
9394
'wrap!' => func(_,v) { wrap_plane = Bool(v) },
@@ -195,8 +196,8 @@ func print_ascii_table(*boards) {
195196
var t = table.drawit
196197

197198
if (defined(ANSI) && use_colors) {
198-
t.gsub!(hit_char, ANSI.colored(hit_char, 'bold red'))
199-
t.gsub!(miss_char, ANSI.colored(miss_char, 'yellow'))
199+
t.gsub!(HIT, ANSI.colored(hit_char, 'bold red'))
200+
t.gsub!(AIR, ANSI.colored(miss_char, 'yellow'))
200201
t.gsub!(HEAD, ANSI.colored(head_char, 'bold green'))
201202
}
202203

@@ -208,15 +209,24 @@ func print_ascii_table(*boards) {
208209
}
209210
}
210211

211-
func valid_assignment (play_board, info_board) {
212+
func valid_assignment (play_board, info_board, extra = false) {
212213

213214
[play_board, info_board].zip {|*rows|
214215
rows.zip {|play,info|
216+
215217
if (info == AIR) {
216218
if (play != BLANK) {
217219
return false
218220
}
219221
}
222+
elsif (extra) {
223+
224+
info == BLANK && next
225+
226+
if (info != play) {
227+
return false
228+
}
229+
}
220230
}
221231
}
222232

@@ -333,56 +343,37 @@ func get_letters() {
333343
return letters
334344
}
335345

336-
func valid (play_board, info_board) {
337-
338-
[play_board, info_board].zip {|*rows|
339-
rows.zip {|play,info|
340-
341-
info == BLANK && next
342-
343-
if (info == AIR) {
344-
if (play != BLANK) {
345-
return false
346-
}
347-
}
348-
elsif (info != play) {
349-
return false
350-
}
351-
}
352-
}
353-
354-
return true
355-
}
356-
357346
func solve(callback) {
358347

359348
var tries = 0
360-
var info_board = BOARD_SIZE.of { BOARD_SIZE.of { BLANK } }
349+
var info_board = make_play_board()
361350
var boards = make_play_boards(info_board)
362351

363352
loop {
364353
for board,plane_count in (boards) {
365354

366355
var play_board = board.dclone
367356
guess(info_board, play_board, plane_count) || next
368-
valid(play_board, info_board) || next
357+
valid_assignment(play_board, info_board, true) || next
369358

370359
var all_dead = true
371360
var new_info = false
372361

373-
var head_pos = get_head_positions(play_board).shuffle
362+
# Prefer points nearest to the center of the board
363+
var head_pos = get_head_positions(play_board).sort_by {|p|
364+
hypot(p.map {|i| (BOARD_SIZE-1)/2 - i }...)
365+
}
374366

375367
head_pos = head_pos.grep_2d {|x,y| info_board[x][y] == BLANK }.map_2d {|x,y|
376-
[x, y, DIRECTIONS.first_by {|d|
377-
(pointers(play_board, x, y, d).count_by { *_ == HIT } == 7) &&
378-
(pointers(info_board, x, y, d).none { *_ == AIR })
368+
[x, y, DIRECTIONS.map {|d| pointers(info_board, x, y, d) }.grep {|t|
369+
t && t.none { *_ == AIR }
379370
}]
380371
}
381372

382373
# Prefer the planes with the most hits
383374
head_pos = head_pos.sort_by {|p|
384-
pointers(info_board, p[0], p[1], p[2]).count_by { *_ == HIT }
385-
}.flip
375+
p[2].sum_by {|t| t.count_by { *_ == HIT } } -> neg
376+
}
386377

387378
head_pos.each_2d {|i,j|
388379

@@ -391,7 +382,7 @@ func solve(callback) {
391382
}
392383

393384
all_dead = false
394-
var score = callback(i, j, play_board, info_board)
385+
var score = callback(i, j, play_board, info_board) \\ return nil
395386

396387
if (score == BLANK) {
397388
score = AIR
@@ -432,13 +423,13 @@ func process_user_input(i, j, play_board, info_board) {
432423
loop {
433424
say "=> My guess: #{indices2letters{i}}#{j+1}"
434425
say "=> Score (hit, head or air)"
435-
var input = (Sys.scanln("> ") \\ break -> lc)
436-
input ~~ ['q', 'quit'] && break
426+
var input = (Sys.scanln("> ") \\ return nil -> lc)
427+
input ~~ ['q', 'quit'] && return nil
437428

438429
input.trim!
439430

440431
score_table.has(input) || do {
441-
say ":: Invalid score..."
432+
say "\n:: Invalid score...\n"
442433
next
443434
}
444435

@@ -461,5 +452,7 @@ if (simulate) {
461452
}
462453
else {
463454
var tries = solve(process_user_input)
464-
say "\n:: All planes destroyed in #{tries} tries!\n"
455+
if (defined(tries)) {
456+
say "\n:: All planes destroyed in #{tries} tries!\n"
457+
}
465458
}

Games/asciiplanes.sf

+4-5
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ var plane_chars = ['$', '#', '@']
3535

3636
var use_colors = defined(ANSI)
3737
var wrap_plane = false
38-
var hit_char = %q{*}
38+
var hit_char = %q{O}
3939
var miss_char = %q{`}
4040

4141
func usage {
@@ -68,10 +68,9 @@ func ver {
6868
}
6969

7070
if (ARGV) {
71-
var getopt = (
72-
try { frequire('Getopt::Long') }
73-
catch { STDERR.print("Can't load the 'Getopt::Long' Perl module...\n"); Sys.exit(2) }
74-
)
71+
var getopt =
72+
try { frequire('Getopt::Long') }
73+
catch { STDERR.print("Can't load the 'Getopt::Long' Perl module...\n"); Sys.exit(2) }
7574

7675
getopt.GetOptions(
7776
'board-size|size=i' => func(_,v) { BOARD_SIZE = Num(v) },

0 commit comments

Comments
 (0)