/* * map_strategy: * open always succeeds, I/O always fails, other functions * perform their function */ int mapstrategy(RP rp) { switch (rp->rp_cmd) { case CMDInit: return map_init(rp); case CMDClose: return map_close(rp); case CMDOpen: return map_open(); case CMDShutdown: return map_shutdown(); case CMDGenIOCTL: return map_ioctl(rp); case CMDINPUT: case CMDOUTPUT: RWCNT(rp) = 0; return RPDONE; case CMDOUTPUTV: case CMDInputF: case CMDOutputF: case CMDInputS: case CMDOutputS: default: return RP_EBAD; } }
/* Put things back to normal */ void game_close(void) { if( client.connected ) cl_network_disconnect(); particle_clear(); if( map ) map_close(&map); }
int map_free(jk_map_t **m) { int rc = JK_FALSE; if(m && *m) { map_close(*m); free(*m); *m = NULL; } return rc; }
int map_write(FSInfo *fs, char *path) { FileHandle *root; FileHandle *bad; if (!map_open_write(path)) return 0; if ((root = file_open_root(fs)) == 0) return 0; walk_dir(root); file_close(root); map_close(); return 1; }
/* loads the city level */ void load_city(int populate) { int i,j; pml ml; char site; map *city; map *maze; initrand(E_CITY, 0); /* Get the hedge maze (which is in the city). */ maze = map_open(MAP_hedges); /* Choose a random level from it. */ map_setLevel(maze, random_range(map_getDepth(maze))); /* Get the city. */ city = map_open(MAP_city); map_setLevel(city,0); TempLevel = Level; if (ok_to_free(TempLevel)) { #ifndef SAVE_LEVELS free_level(TempLevel); #endif TempLevel = NULL; } #ifndef SAVE_LEVELS Level = ((plv) checkmalloc(sizeof(levtype))); #else msdos_changelevel(TempLevel,0,-1); Level = &TheLevel; #endif clear_level(Level); Level->depth = 0; Level->environment = E_CITY; /* WDT: Rampart, as a special case, has its width stored in a * global variable. */ WIDTH = Level->level_width = map_getWidth(city); LENGTH = Level->level_length = map_getLength(city); for(j=0; j<Level->level_length; j++) { for(i=0; i<Level->level_width; i++) { lset(i,j,SEEN); site = map_getSiteChar(city,i,j); switch(site) { /* case '@': Player.x = i; Player.y = j; Level->site[i][j].locchar = FLOOR; break; */ case 'g': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_GARDEN; break; case 'y': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_CEMETARY; break; case 'p': /* WDT: each of these places needs to be assigned * a function (or replaced with an 'x' in the map) */ case '!': case 'I': case 'E': case 'e': case 'x': assign_city_function(i,j); break; case 't': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_TEMPLE; CitySiteList[L_TEMPLE-CITYSITEBASE][0] = TRUE; CitySiteList[L_TEMPLE-CITYSITEBASE][1] = i; CitySiteList[L_TEMPLE-CITYSITEBASE][2] = j; break; #if 0 /* WDT: HACK! The new city doesn't use portcullis traps, but has other * uses for 'T'. Um... I'd rather have a use for them (that's what * the jail is supposed to be), so this will stay only for now; with * any luck we'll have things fixed up before the next release. */ case 'T': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_PORTCULLIS_TRAP; Level->site[i][j].aux = NOCITYMOVE; break; #endif /* end of hack */ case 'R': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_RAISE_PORTCULLIS; Level->site[i][j].aux = NOCITYMOVE; break; case '7': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_PORTCULLIS; Level->site[i][j].aux = NOCITYMOVE; break; case 'C': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_COLLEGE; CitySiteList[L_COLLEGE-CITYSITEBASE][0] = TRUE; CitySiteList[L_COLLEGE-CITYSITEBASE][1] = i; CitySiteList[L_COLLEGE-CITYSITEBASE][2] = j; break; case 's': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_SORCERORS; CitySiteList[L_SORCERORS-CITYSITEBASE][0] = TRUE; CitySiteList[L_SORCERORS-CITYSITEBASE][1] = i; CitySiteList[L_SORCERORS-CITYSITEBASE][2] = j; break; case 'M': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_MERC_GUILD; CitySiteList[L_MERC_GUILD-CITYSITEBASE][0] = TRUE; CitySiteList[L_MERC_GUILD-CITYSITEBASE][1] = i; CitySiteList[L_MERC_GUILD-CITYSITEBASE][2] = j; break; case 'K': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_MONASTERY; CitySiteList[L_MONASTERY-CITYSITEBASE][0] = TRUE; CitySiteList[L_MONASTERY-CITYSITEBASE][1] = i; CitySiteList[L_MONASTERY-CITYSITEBASE][2] = j; break; case 'c': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_CASTLE; CitySiteList[L_CASTLE-CITYSITEBASE][0] = TRUE; CitySiteList[L_CASTLE-CITYSITEBASE][1] = i; CitySiteList[L_CASTLE-CITYSITEBASE][2] = j; break; case '?': { static int myI = -1, myJ; char site; if ( myI == -1 ) { /* If this is the first time we've seen the hedge maze, * set this as its corner. */ myI = i; myJ = j; } site = map_getSiteChar(maze, i - myI, j - myJ); mazesite(site,i,j,populate); } break; case 'P': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_ORDER; CitySiteList[L_ORDER-CITYSITEBASE][0] = TRUE; CitySiteList[L_ORDER-CITYSITEBASE][1] = i; CitySiteList[L_ORDER-CITYSITEBASE][2] = j; break; case 'H': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_CHARITY; CitySiteList[L_CHARITY-CITYSITEBASE][0] = TRUE; CitySiteList[L_CHARITY-CITYSITEBASE][1] = i; CitySiteList[L_CHARITY-CITYSITEBASE][2] = j; break; case 'h': Level->site[i][j].locchar = FLOOR; if (populate) make_horse(i,j); /* from village.c */ break; case 'j': Level->site[i][j].locchar = FLOOR; if (populate) make_justiciar(i,j); break; case 'J': Level->site[i][j].locchar = CLOSED_DOOR; Level->site[i][j].p_locf = L_JAIL; break; case 'A': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_ARENA; CitySiteList[L_ARENA-CITYSITEBASE][0] = TRUE; CitySiteList[L_ARENA-CITYSITEBASE][1] = i; CitySiteList[L_ARENA-CITYSITEBASE][2] = j; break; case 'B': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_BANK; CitySiteList[L_BANK-CITYSITEBASE][0] = TRUE; CitySiteList[L_BANK-CITYSITEBASE][1] = i; CitySiteList[L_BANK-CITYSITEBASE][2] = j; lset(i,j,STOPS); lset(i,j+1,STOPS); lset(i+1,j,STOPS); lset(i-1,j,STOPS); lset(i,j-1,STOPS); break; case 'i': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].p_locf = L_TOURIST; CitySiteList[L_TOURIST-CITYSITEBASE][1] = i; CitySiteList[L_TOURIST-CITYSITEBASE][2] = j; lset(i,j,STOPS); lset(i,j+1,STOPS); lset(i+1,j,STOPS); lset(i-1,j,STOPS); lset(i,j-1,STOPS); break; case 'X': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_COUNTRYSIDE; CitySiteList[L_COUNTRYSIDE-CITYSITEBASE][0] = TRUE; CitySiteList[L_COUNTRYSIDE-CITYSITEBASE][1] = i; CitySiteList[L_COUNTRYSIDE-CITYSITEBASE][2] = j; break; case 'v': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_VAULT; Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case 'S': Level->site[i][j].locchar = FLOOR; Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case 'G': Level->site[i][j].locchar = FLOOR; if (populate) { make_site_monster(i,j,GUARD); Level->site[i][j].creature->aux1 = i; Level->site[i][j].creature->aux2 = j; } break; case 'u': Level->site[i][j].locchar = FLOOR; if (populate) make_minor_undead(i,j); break; case 'U': Level->site[i][j].locchar = FLOOR; if (populate) make_major_undead(i,j); break; case 'V': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_VAULT; if (populate) make_site_treasure(i,j,5); Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case '%': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_TRAP_SIREN; if (populate) make_site_treasure(i,j,5); Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case '$': Level->site[i][j].locchar = FLOOR; if (populate) make_site_treasure(i,j,5); break; case '2': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = ODIN; break; case '3': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = SET; break; case '4': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = ATHENA; break; case '5': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = HECATE; break; case '6': Level->site[i][j].locchar = ALTAR; Level->site[i][j].p_locf = L_ALTAR; Level->site[i][j].aux = DESTINY; break; case '^': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = TRAP_BASE+random_range(NUMTRAPS); lset(i,j,SECRET); break; case '"': Level->site[i][j].locchar = HEDGE; break; case '~': Level->site[i][j].locchar = WATER; Level->site[i][j].p_locf = L_WATER; break; case '=': Level->site[i][j].locchar = WATER; Level->site[i][j].p_locf = L_MAGIC_POOL; break; case '*': Level->site[i][j].locchar = WALL; Level->site[i][j].aux = 10; break; case '#': Level->site[i][j].locchar = WALL; Level->site[i][j].aux = 500; break; case 'T':/* currently meaningless in large city map. */ case '>': /* currently meaningless outside of maze.*/ case '.': Level->site[i][j].locchar = FLOOR; break; case ',': Level->site[i][j].showchar = WALL; Level->site[i][j].locchar = FLOOR; Level->site[i][j].aux = NOCITYMOVE; lset(i,j,SECRET); break; case '-': case 'D': /* WDT: should all Ds be changed to -, or should D be given * special treatment? */ Level->site[i][j].locchar = CLOSED_DOOR; break; case '1': Level->site[i][j].locchar = STATUE; break; default: printf("\nOops... missed a case [%d,%d]: '%c' (%d)\n", i,j,site,site); morewait(); } if (loc_statusp(i,j,SEEN)) { if (loc_statusp(i,j,SECRET)) Level->site[i][j].showchar = WALL; else Level->site[i][j].showchar = Level->site[i][j].locchar; } } } map_close(maze); map_close(city); City = Level; /* make all city monsters asleep, and shorten their wakeup range to 2 */ /* to prevent players from being molested by vicious monsters on */ /* the streets */ for(ml=Level->mlist; ml!=NULL; ml=ml->next) { m_status_reset(ml->m,AWAKE); ml->m->wakeup = 2; } initrand(E_RESTORE, 0); }
/** * @brief Cleans up the map stuff. */ void map_cleanup (void) { map_close(); map_clear(); }
/* loads the house level into Level*/ void load_house(int kind, int populate) { map *home; int i,j; char site; int stops; TempLevel = Level; initrand(Current_Environment, Player.x + Player.y + hour()*10); if (ok_to_free(TempLevel)) { #ifndef SAVE_LEVELS free_level(TempLevel); #endif TempLevel = NULL; } #ifndef SAVE_LEVELS Level = ((plv) checkmalloc(sizeof(levtype))); #else msdos_changelevel(TempLevel,0,-1); Level = &TheLevel; #endif clear_level(Level); switch(kind) { case E_HOUSE: home = map_open(MAP_house); break; case E_MANSION: home = map_open(MAP_mansion); break; default: case E_HOVEL: home = map_open(MAP_hovel); break; } Level->level_width=map_getWidth(home); Level->level_length=map_getLength(home); map_setLevel(home, 0); stops = 0; for(j=0;j<Level->level_length;j++) { for(i=0;i<Level->level_width;i++) { if (kind == E_HOVEL) Level->site[i][j].lstatus = SEEN; else Level->site[i][j].lstatus = 0; Level->site[i][j].roomnumber = RS_CORRIDOR; Level->site[i][j].p_locf = L_NO_OP; site = map_getSiteChar(home,i,j); switch(site) { case 'N': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_BEDROOM; if (random_range(2) && populate) make_house_npc(i,j); break; case 'H': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_BEDROOM; if (random_range(2) && populate) make_mansion_npc(i,j); break; case 'D': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_DININGROOM; break; case '.': Level->site[i][j].locchar = FLOOR; if (stops) { lset(i,j,STOPS); stops = 0; } break; case 'c': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_CLOSET; break; case 'G': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_BATHROOM; break; case 'B': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_BEDROOM; break; case 'K': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_KITCHEN; break; case 'S': Level->site[i][j].locchar = FLOOR; Level->site[i][j].showchar = WALL; lset(i,j,SECRET); Level->site[i][j].roomnumber = RS_SECRETPASSAGE; break; case '3': Level->site[i][j].locchar = SAFE; Level->site[i][j].showchar = WALL; lset(i,j,SECRET); Level->site[i][j].p_locf = L_SAFE; break; case '^': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = TRAP_BASE+random_range(NUMTRAPS); break; case 'P': Level->site[i][j].locchar = PORTCULLIS; Level->site[i][j].p_locf = L_PORTCULLIS; break; case 'R': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_RAISE_PORTCULLIS; break; case 'p': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_PORTCULLIS; break; case 'T': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_PORTCULLIS_TRAP; break; case 'X': Level->site[i][j].locchar = FLOOR; Level->site[i][j].p_locf = L_HOUSE_EXIT; stops = 1; break; case '#': Level->site[i][j].locchar = WALL; switch (kind) { case E_HOVEL: Level->site[i][j].aux = 10; break; case E_HOUSE: Level->site[i][j].aux = 50; break; case E_MANSION: Level->site[i][j].aux = 150; break; } break; case '|': Level->site[i][j].locchar = OPEN_DOOR; Level->site[i][j].roomnumber = RS_CORRIDOR; lset(i,j,STOPS); break; case '+': Level->site[i][j].locchar = CLOSED_DOOR; Level->site[i][j].roomnumber = RS_CORRIDOR; Level->site[i][j].aux = LOCKED; lset(i,j,STOPS); break; case 'd': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_CORRIDOR; if (populate) make_site_monster(i,j,DOBERMAN); break; case 'a': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_CORRIDOR; Level->site[i][j].p_locf = L_TRAP_SIREN; break; case 'A': Level->site[i][j].locchar = FLOOR; Level->site[i][j].roomnumber = RS_CORRIDOR; if (populate) make_site_monster(i,j,AUTO_MINOR); /* automaton */ break; } Level->site[i][j].showchar = ' '; } } map_close(home); initrand(E_RESTORE, 0); }
static void lka_imsg(struct imsgev *iev, struct imsg *imsg) { struct submit_status *ss; struct secret *secret; struct mapel *mapel; struct rule *rule; struct map *map; struct map *mp; void *tmp; if (imsg->hdr.type == IMSG_DNS_HOST || imsg->hdr.type == IMSG_DNS_MX || imsg->hdr.type == IMSG_DNS_PTR) { dns_async(iev, imsg->hdr.type, imsg->data); return; } if (iev->proc == PROC_MFA) { switch (imsg->hdr.type) { case IMSG_LKA_MAIL: ss = imsg->data; ss->code = 530; if (ss->u.maddr.user[0] == '\0' && ss->u.maddr.domain[0] == '\0') ss->code = 250; else if (lka_verify_mail(&ss->u.maddr)) ss->code = 250; imsg_compose_event(iev, IMSG_LKA_MAIL, 0, 0, -1, ss, sizeof *ss); return; case IMSG_LKA_RULEMATCH: ss = imsg->data; rule = ruleset_match(&ss->envelope); if (rule == NULL) ss->code = (errno == EAGAIN) ? 451 : 530; else ss->code = (rule->r_decision == R_ACCEPT) ? 250 : 530; imsg_compose_event(iev, IMSG_LKA_RULEMATCH, 0, 0, -1, ss, sizeof *ss); return; case IMSG_LKA_RCPT: lka_session(imsg->data); return; } } if (iev->proc == PROC_MTA) { switch (imsg->hdr.type) { case IMSG_LKA_SECRET: { struct map_credentials *map_credentials; secret = imsg->data; map = map_findbyname(secret->mapname); if (map == NULL) { log_warn("warn: lka: credentials map %s is missing", secret->mapname); imsg_compose_event(iev, IMSG_LKA_SECRET, 0, 0, -1, secret, sizeof *secret); return; } map_credentials = map_lookup(map->m_id, secret->host, K_CREDENTIALS); log_debug("debug: lka: %s credentials lookup (%d)", secret->host, map_credentials != NULL); secret->secret[0] = '\0'; if (map_credentials == NULL) log_warnx("warn: %s credentials not found", secret->host); else if (lka_encode_credentials(secret->secret, sizeof secret->secret, map_credentials) == 0) log_warnx("warn: %s credentials parse fail", secret->host); imsg_compose_event(iev, IMSG_LKA_SECRET, 0, 0, -1, secret, sizeof *secret); free(map_credentials); return; } } } if (iev->proc == PROC_PARENT) { switch (imsg->hdr.type) { case IMSG_CONF_START: env->sc_rules_reload = xcalloc(1, sizeof *env->sc_rules, "lka:sc_rules_reload"); env->sc_maps_reload = xcalloc(1, sizeof *env->sc_maps, "lka:sc_maps_reload"); TAILQ_INIT(env->sc_rules_reload); TAILQ_INIT(env->sc_maps_reload); return; case IMSG_CONF_RULE: rule = xmemdup(imsg->data, sizeof *rule, "lka:rule"); TAILQ_INSERT_TAIL(env->sc_rules_reload, rule, r_entry); return; case IMSG_CONF_MAP: map = xmemdup(imsg->data, sizeof *map, "lka:map"); TAILQ_INIT(&map->m_contents); TAILQ_INSERT_TAIL(env->sc_maps_reload, map, m_entry); tmp = env->sc_maps; env->sc_maps = env->sc_maps_reload; mp = map_open(map); if (mp == NULL) errx(1, "lka: could not open map \"%s\"", map->m_name); map_close(map, mp); env->sc_maps = tmp; return; case IMSG_CONF_RULE_SOURCE: rule = TAILQ_LAST(env->sc_rules_reload, rulelist); tmp = env->sc_maps; env->sc_maps = env->sc_maps_reload; rule->r_sources = map_findbyname(imsg->data); if (rule->r_sources == NULL) fatalx("lka: maps inconsistency"); env->sc_maps = tmp; return; case IMSG_CONF_MAP_CONTENT: map = TAILQ_LAST(env->sc_maps_reload, maplist); mapel = xmemdup(imsg->data, sizeof *mapel, "lka:mapel"); TAILQ_INSERT_TAIL(&map->m_contents, mapel, me_entry); return; case IMSG_CONF_END: if (env->sc_rules) purge_config(PURGE_RULES); if (env->sc_maps) purge_config(PURGE_MAPS); env->sc_rules = env->sc_rules_reload; env->sc_maps = env->sc_maps_reload; /* start fulfilling requests */ event_add(&env->sc_ievs[PROC_MTA]->ev, NULL); event_add(&env->sc_ievs[PROC_MFA]->ev, NULL); event_add(&env->sc_ievs[PROC_SMTP]->ev, NULL); return; case IMSG_CTL_VERBOSE: log_verbose(*(int *)imsg->data); return; case IMSG_PARENT_FORWARD_OPEN: lka_session_forward_reply(imsg->data, imsg->fd); return; } } if (iev->proc == PROC_CONTROL) { switch (imsg->hdr.type) { case IMSG_LKA_UPDATE_MAP: map = map_findbyname(imsg->data); if (map == NULL) { log_warnx("warn: lka: no such map \"%s\"", (char *)imsg->data); return; } map_update(map); return; } } errx(1, "lka_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); }
MAP *map_new(unsigned int width, unsigned int height, unsigned int terrain_layers, DARNIT_TILESHEET *ts) { int i, j; int tile_w, tile_h; int fail=0; DARNIT_MAP *d_map=NULL; DARNIT_MAP_LAYER *layer=NULL; MAP *map; DARNIT_FILE *f_ts; if(!(map=malloc(sizeof(MAP)))) return NULL; if(!(ts&&terrain_layers&&(d_map=malloc(sizeof(DARNIT_MAP)))&&(layer=malloc((terrain_layers+2)*sizeof(DARNIT_MAP_LAYER))))) { free(d_map); free(layer); return NULL; } d_map->layer=layer; *((unsigned int *) &d_map->layers)=terrain_layers+2; d_map->object=NULL; *((unsigned int *) &d_map->objects)=0; d_map->prop=NULL; d_map->stringdata=NULL; d_map->stringrefs=NULL; d_render_tilesheet_geometrics(ts, NULL, NULL, &tile_w, &tile_h); for(i=0; i<terrain_layers+2; i++) { /*This is needed to at least null all tilemaps so we can free them i one fails*/ if(!(fail|=!(layer[i].tilemap=d_tilemap_new(0xFFF, ts, 0xFFF, width, height)))) { for(j=0; j<width*height; j++) layer[i].tilemap->data[j]=i==terrain_layers+1?1:144*(!i); d_tilemap_recalc(layer[i].tilemap); } layer[i].ts=ts; layer[i].offset_x=0; layer[i].offset_y=0; layer[i].tile_w=tile_w; layer[i].tile_h=tile_h; } if(fail) { for(i=0; i<terrain_layers+2; i++) d_tilemap_free(layer[i].tilemap); free(d_map); free(layer); return NULL; } d_map_camera_move(d_map, 0, 0); map->map=d_map; map->stringtable=malloc(sizeof(MAP_PROPERTY)); map->stringtable->key="tileset"; map->stringtable->value="mapdata/default.png"; map->stringtable->next=NULL; map->w=width*tile_w; map->h=height*tile_h; sprintf(map->sizestring, "%ix%i", width, height); map_prop_set_or_add(map, "size", map->sizestring); if(!(f_ts=d_file_open("res/default.png", "rb"))) { map->tilesheet=NULL; map_close(map); return NULL; } d_file_seek(f_ts, 0, SEEK_END); map->tilesheet_size=d_file_tell(f_ts); map->tilesheet=malloc(map->tilesheet_size); d_file_seek(f_ts, 0, SEEK_SET); d_file_read(map->tilesheet, map->tilesheet_size, f_ts); d_file_close(f_ts); return map; }