Skip to content

Commit 3fef4a6

Browse files
committed
FIX: step -> jericho_step to avoid name clashing with regexp.c:step function; ENH: filter_candidate_actions relies on state hashes instead world_diff.
1 parent 87387e6 commit 3fef4a6

File tree

5 files changed

+41
-212
lines changed

5 files changed

+41
-212
lines changed

frotz/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ CFLAGS += -w
2020
# OPTS = -O3 -fomit-frame-pointer -falign-functions=2 -falign-loops=2 -falign-jumps=2 -fPIC
2121
OPTS = -O3 -fPIC
2222
# These are handy for debugging.
23-
# OPTS = $(CFLAGS) -g -fPIC
23+
# OPTS = $(CFLAGS) -O3 -g -fPIC # With optimization (faster code)
24+
# OPTS = $(CFLAGS) -g -fPIC # Without optimization (slower code)
2425
# These are handy for profiling
2526
# OPTS = $(CFLAGS) -pg -fPIC
2627

frotz/src/interface/frotz_interface.c

Lines changed: 18 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,6 @@ zobject* new_objs = NULL;
9292
int ram_diff_cnt;
9393
zword ram_diff_addr[16];
9494
zword ram_diff_value[16];
95-
//char last_state_hash[64];
96-
//char current_state_hash[64];
9795
bool state_has_changed = FALSE;
9896

9997

@@ -187,7 +185,7 @@ enum SUPPORTED {
187185

188186
// Set ROM_IDX according to the story_file.
189187
void load_rom_bindings(char *story_file) {
190-
char md5_hash[64];
188+
char md5_hash[32];
191189
char *start;
192190

193191
FILE * f = fopen (story_file, "r");
@@ -333,6 +331,14 @@ void shutdown() {
333331
free(special_ram_values);
334332
special_ram_values = NULL;
335333
}
334+
if (new_objs != NULL) {
335+
free(new_objs);
336+
new_objs = NULL;
337+
}
338+
if (old_objs != NULL) {
339+
free(old_objs);
340+
old_objs = NULL;
341+
}
336342
}
337343

338344
// Save the state of the game into a string buffer
@@ -1568,10 +1574,6 @@ char* setup(char *story_file, int seed, void *rom, size_t rom_size) {
15681574
run_free();
15691575
}
15701576

1571-
// Initialize last and current state hashes.
1572-
// get_world_state_hash(last_state_hash);
1573-
// get_world_state_hash(current_state_hash);
1574-
15751577
// Concatenate upper and lower screens.
15761578
strcat(world, dumb_get_lower_screen());
15771579
strcat(world, dumb_get_upper_screen());
@@ -1583,24 +1585,16 @@ char* setup(char *story_file, int seed, void *rom, size_t rom_size) {
15831585
return world;
15841586
}
15851587

1586-
char* step(char *next_action) {
1587-
char* text;
1588-
char last_state_hash[64];
1589-
char current_state_hash[64];
1590-
1588+
char* jericho_step(char *next_action) {
15911589
if (emulator_halted > 0)
15921590
return halted_message;
15931591

1594-
// get_world_state_hash(last_state_hash);
1595-
15961592
// Swap old_objs and new_objs.
15971593
zobject* tmp;
15981594
tmp = old_objs;
15991595
old_objs = new_objs;
16001596
new_objs = tmp;
16011597

1602-
// printf("%x, %x\n", old_objs, new_objs);
1603-
16041598
// Clear the object, attr, and ram diffs
16051599
move_diff_cnt = 0;
16061600
attr_diff_cnt = 0;
@@ -1617,20 +1611,7 @@ char* step(char *next_action) {
16171611

16181612
// Check for changes to special ram
16191613
update_ram_diff();
1620-
//get_world_state_hash(current_state_hash);
1621-
16221614
update_objs_tracker();
1623-
// // memset(new_objs, 0, (get_num_world_objs() + 1) * sizeof(zobject));
1624-
// get_world_objects(new_objs, TRUE);
1625-
1626-
// // For a more robust state hash, do not include siblings and children
1627-
// // since their ordering in memory may change.
1628-
// for (int i=1; i<=get_num_world_objs(); ++i) {
1629-
// new_objs[i].sibling = 0;
1630-
// new_objs[i].child = 0;
1631-
// }
1632-
1633-
//state_has_changed = strcmp(current_state_hash, last_state_hash) != 0;
16341615
state_has_changed = memcmp(old_objs, new_objs, (get_num_world_objs() + 1) * sizeof(zobject)) != 0;
16351616
// printf("%s =(%d)= %s <== %s", current_state_hash, state_has_changed, last_state_hash, next_action);
16361617

@@ -1715,33 +1696,7 @@ char* get_current_state() {
17151696
// Returns 1 if the last action changed the state of the world.
17161697
int world_changed() {
17171698
int objs_has_changed = state_has_changed;
1718-
//return state_has_changed;
1719-
1720-
// int i;
1721-
// for (i=0; i<move_diff_cnt; ++i) {
1722-
// if (ignore_moved_obj(move_diff_objs[i], move_diff_dest[i])) {
1723-
// continue;
1724-
// }
1725-
// return 1;
1726-
// }
1727-
// for (i=0; i<attr_diff_cnt; ++i) {
1728-
// if (ignore_attr_diff(attr_diff_objs[i], attr_diff_nb[i])) {
1729-
// continue;
1730-
// }
1731-
// return 1;
1732-
// }
1733-
// for (i=0; i<attr_clr_cnt; ++i) {
1734-
// if (ignore_attr_clr(attr_clr_objs[i], attr_clr_nb[i])) {
1735-
// continue;
1736-
// }
1737-
// return 1;
1738-
// }
1739-
// for (i=0; i<prop_put_cnt; ++i) {
1740-
// // if (ignore_prop_put(prop_put_objs[i], prop_put_nb[i])) {
1741-
// // continue;
1742-
// // }
1743-
// return 1;
1744-
// }
1699+
17451700
if (game_over() > 0 || victory() > 0) {
17461701
return 1;
17471702
}
@@ -1766,10 +1721,6 @@ void get_object(zobject *obj, zword obj_num) {
17661721
zbyte length;
17671722
LOW_BYTE(obj_name_addr, length);
17681723

1769-
// if (length <= 0 || length > 64) {
1770-
// return;
1771-
// }
1772-
17731724
(*obj).num = obj_num;
17741725

17751726
if (length > 0 && length <= 64) {
@@ -1985,54 +1936,26 @@ void get_world_state_hash(char* md5_hash) {
19851936

19861937
int n_objs = get_num_world_objs() + 1; // Add extra spot for zero'th object
19871938
size_t objs_size = n_objs * sizeof(zobject);
1988-
zobject* objs = calloc(n_objs, sizeof(zobject));
19891939

19901940
size_t ram_size = get_special_ram_size() * sizeof(unsigned char);
19911941
unsigned char* ram = malloc(ram_size);
19921942
get_special_ram(ram);
19931943

19941944
int retPC = getRetPC();
19951945

1996-
get_world_objects(objs, TRUE);
1997-
1998-
// For a more robust state hash, do not include siblings and children
1999-
// since their ordering in memory may change.
2000-
for (int i=1; i<=get_num_world_objs(); ++i) {
2001-
objs[i].sibling = 0;
2002-
objs[i].child = 0;
2003-
}
2004-
2005-
// Debug print.
2006-
// printf("\n--Start-\n");
2007-
// for (int k=0; k != n_objs; ++k) {
2008-
// print_object2(&objs[k]);
2009-
// }
2010-
// printf("\n--End-\n");
2011-
2012-
// char temp_md5_hash[64];
2013-
// FILE* tmp_fp = fmemopen(objs, objs_size, "rb");
2014-
// sum(tmp_fp, temp_md5_hash);
2015-
// fclose(tmp_fp);
2016-
// printf("temp_md5_hash: %s", temp_md5_hash);
2017-
20181946
size_t state_size = objs_size + ram_size + sizeof(int);
20191947
char* state = malloc(state_size);
2020-
memcpy(state, objs, objs_size);
1948+
memcpy(state, new_objs, objs_size);
20211949
memcpy(&state[objs_size], ram, ram_size);
20221950
memcpy(&state[objs_size+ram_size], &retPC, sizeof(int));
20231951

2024-
// int chk = checksum(state, state_size);
2025-
// sprintf(md5_hash, "%2X", chk);
2026-
20271952
FILE* fp = fmemopen(state, state_size, "rb");
20281953
sum(fp, md5_hash);
20291954
fclose(fp);
20301955

20311956
// printf("md5 (objs): %s\n", md5_hash);
20321957

2033-
free(objs);
20341958
free(state);
2035-
return 0;
20361959
}
20371960

20381961
// Teleports an object (and all children) to the desired destination
@@ -2063,9 +1986,10 @@ void test() {
20631986
// candidate_actions contains a string with all the candidate actions, seperated by ';'
20641987
// valid_actions will be written with each of the identified valid actions seperated by ';'
20651988
// diff_array will be written with the world_diff for each valid_action indicating
2066-
// which of the valid actions are equivalent to each other in terms of their world diffs.
1989+
// which of the valid actions are equivalent to each other in terms of their state hashes.
20671990
// Returns the number of valid actions found.
2068-
int filter_candidate_actions(char *candidate_actions, char *valid_actions, zword *diff_array) {
1991+
int filter_candidate_actions(char *candidate_actions, char *valid_actions, char *hashes) {
1992+
20691993
char *act = NULL;
20701994
char *act_newline = NULL;
20711995
char *text;
@@ -2106,22 +2030,7 @@ int filter_candidate_actions(char *candidate_actions, char *valid_actions, zword
21062030
act_newline = malloc(strlen(act) + 2);
21072031
strcpy(act_newline, act);
21082032
strcat(act_newline, "\n");
2109-
2110-
// Step: Code is copied due to inexplicable segfault when calling step() directly; Ugh!
2111-
move_diff_cnt = 0;
2112-
attr_diff_cnt = 0;
2113-
attr_clr_cnt = 0;
2114-
prop_put_cnt = 0;
2115-
ram_diff_cnt = 0;
2116-
update_special_ram();
2117-
dumb_set_next_action(act_newline);
2118-
zstep();
2119-
run_free();
2120-
update_ram_diff();
2121-
text = dumb_get_screen();
2122-
text = clean_observation(text);
2123-
strcpy(world, text);
2124-
dumb_clear_screen();
2033+
text = jericho_step(act_newline);
21252034

21262035
if (emulator_halted > 0) {
21272036
printf("Emulator halted on action: %s\n", act);
@@ -2137,7 +2046,7 @@ int filter_candidate_actions(char *candidate_actions, char *valid_actions, zword
21372046
valid_actions[v_idx++] = ';';
21382047

21392048
// Write the world diff resulting from the last action.
2140-
get_cleaned_world_diff(&diff_array[128*valid_cnt], &diff_array[(128*valid_cnt) + 64]); // TODO: replace 128
2049+
get_world_state_hash(&hashes[32*valid_cnt]);
21412050
valid_cnt++;
21422051
}
21432052
}
@@ -2151,6 +2060,7 @@ int filter_candidate_actions(char *candidate_actions, char *valid_actions, zword
21512060
setFP(fp_cpy);
21522061
set_opcode(next_opcode_cpy);
21532062
setFrameCount(frame_count_cpy);
2063+
update_objs_tracker();
21542064

21552065
act = strtok(NULL, ";");
21562066
free(act_newline);

frotz/src/interface/frotz_interface.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ extern char* setup(char *story_file, int seed, void* rom, size_t rom_size);
3939

4040
extern void shutdown();
4141

42-
extern char* step(char *next_action);
42+
extern char* jericho_step(char *next_action);
4343

4444
extern int save(char *filename);
4545

@@ -51,7 +51,8 @@ extern int getRAMSize();
5151

5252
extern void getRAM(unsigned char *ram);
5353

54-
int filter_candidate_actions(char *candidate_actions, char *valid_actions, zword *diff_array);
54+
// int filter_candidate_actions(char *candidate_actions, char *valid_actions, zword *diff_array);
55+
int filter_candidate_actions(char *candidate_actions, char *valid_actions, char *hashes);
5556

5657
extern char world[256 + 8192];
5758

jericho/jericho.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,8 @@ def _load_frotz_lib():
238238
frotz_lib.setup.restype = c_char_p
239239
frotz_lib.shutdown.argtypes = []
240240
frotz_lib.shutdown.restype = None
241-
frotz_lib.step.argtypes = [c_char_p]
242-
frotz_lib.step.restype = c_char_p
241+
frotz_lib.jericho_step.argtypes = [c_char_p]
242+
frotz_lib.jericho_step.restype = c_char_p
243243
frotz_lib.save.argtypes = [c_char_p]
244244
frotz_lib.save.restype = int
245245
frotz_lib.restore.argtypes = [c_char_p]
@@ -498,7 +498,7 @@ def step(self, action):
498498
:rtype: string, float, boolean, dictionary
499499
'''
500500
old_score = self.frotz_lib.get_score()
501-
next_state = self.frotz_lib.step((action+'\n').encode('utf-8')).decode('cp1252')
501+
next_state = self.frotz_lib.jericho_step((action+'\n').encode('utf-8')).decode('cp1252')
502502
score = self.frotz_lib.get_score()
503503
reward = score - old_score
504504
return next_state, reward, (self.game_over() or self.victory()),\
@@ -765,7 +765,7 @@ def get_world_state_hash(self):
765765
'79c750fff4368efef349b02ff50ffc23'
766766
767767
"""
768-
md5_hash = np.zeros(64, dtype=np.uint8)
768+
md5_hash = np.zeros(32, dtype=np.uint8)
769769
self.frotz_lib.get_world_state_hash(as_ctypes(md5_hash))
770770
md5_hash = (b"").join(md5_hash.view(c_char)).decode('cp1252')
771771
return md5_hash
@@ -1034,20 +1034,18 @@ def _filter_candidate_actions(self, candidate_actions, use_ctypes=False, use_par
10341034
candidate_str = (";".join(candidate_actions)).encode('utf-8')
10351035
valid_str = (' '*(len(candidate_str)+1)).encode('utf-8')
10361036

1037-
DIFF_SIZE = 128
1038-
diff_array = np.zeros(len(candidate_actions) * DIFF_SIZE, dtype=np.uint16)
1037+
hashes = np.zeros(len(candidate_actions), dtype='S32')
10391038
valid_cnt = self.frotz_lib.filter_candidate_actions(
10401039
candidate_str,
10411040
valid_str,
1042-
as_ctypes(diff_array)
1041+
as_ctypes(hashes.view(np.uint8))
10431042
)
10441043
if self._emulator_halted():
10451044
self.reset()
10461045

10471046
valid_acts = valid_str.decode('cp1252').strip().split(';')[:-1]
10481047
for i in range(valid_cnt):
1049-
diff = tuple(diff_array[i*DIFF_SIZE:(i+1)*DIFF_SIZE])
1050-
diff2acts[diff].append(valid_acts[i])
1048+
diff2acts[hashes[i]].append(valid_acts[i])
10511049

10521050
else:
10531051
orig_score = self.get_score()

0 commit comments

Comments
 (0)