Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # -*- coding: cp1251 -*-
- """Обрабатывает Эксель-файлы для игры Комбикорм-2 в результате получаются t-файлы уровней.
- """
- from openpyxl import Workbook
- import openpyxl
- import sys
- import time
- import datetime
- import argparse
- __author__ = "Anton Lastochkin"
- __copyright__ = "Copyright 2017"
- __credits__ = ["Anton Lastochkin", "Alik Ganzimuradov"]
- __license__ = "GPL"
- __version__ = "1.4"
- #Парсинг аргументов командной строки
- #args.log=True - печать логов
- print('XLSToTads version ' + __version__)
- parser = argparse.ArgumentParser(description='Transform XLSX to Tads game files.')
- parser.add_argument("--log", help="Need full parsing log.",action='store_const', const=True)
- args = parser.parse_args()
- #print args.log
- #raw_input('Press Enter to continue...')
- #exit()
- #карта переводов для инфо, классов и параметров
- #название -> desc
- #прилагательные -> adjective
- #описание ->ldesc
- #константы блоков
- BLOCK_WAIT = "WAIT"
- BLOCK_INFO = ("инфо").decode('cp1251')
- BLOCK_MAP = ("карта").decode('cp1251')
- BLOCK_OBJ = ("объекты").decode('cp1251')
- DIALOGUE_EVENT = ("диалоги").decode('cp1251')
- DIALOGUE_WAIT_HEADER = "wait header"
- DIALOGUE_READ_CONTENT = "read content"
- BLOCK_END = ("конец").decode('cp1251')
- ALPHA_FOR_MAP = (" АБВГДЕЖЗИКЛМНОПРСТУФХЦЧ").decode('cp1251')
- # для карты
- GROUND_TYPE_ROCK = ('непроход').decode('cp1251')
- GROUND_TYPE_WALL = ('стена').decode('cp1251')
- GROUND_TYPE_WATER = ('вода').decode('cp1251')
- CELL_TYPE_FINAL = ('финал').decode('cp1251')
- START_TYPE_ZOND = ('зонд').decode('cp1251')
- START_TYPE_KIT = ('кит').decode('cp1251')
- START_TYPE_VINT = ('винт').decode('cp1251')
- START_TYPE_SONYA = ('соня').decode('cp1251')
- # для инфо
- KEY_INFO_CAPTION = ('название').decode('cp1251')
- KEY_INFO_BREEF = ('брифинг').decode('cp1251')
- KEY_INFO_FINAL = ('финал').decode('cp1251')
- KEY_INFO_NEXT = ('следующ').decode('cp1251')
- KEY_INFO_CODE = ('код').decode('cp1251')
- INIT_BLOCK = BLOCK_MAP
- #текущее состояние обработчика блоков
- state = INIT_BLOCK
- levelId = 1
- #текст ячейки в нужной кодировке
- def get_cell_text(cell):
- try:
- t = float(cell.value)
- t = str(t)
- except:
- t = cell.value
- return t
- #получить число из ячейки
- def get_cell_int(cell):
- return int(float(get_cell_text(cell)))
- #вывод текста на консоль в нужной кодировке
- def print_to_console(text,isImportant):
- if isImportant == True or args.log == True:
- print(text.encode('cp866','replace'))
- return
- #перевод координаты вида А1,Б1 в цифровой эквивалент
- def coord_to_pos(coord):
- t_col = coord[1:]
- letter = coord[0]
- n_row = ALPHA_FOR_MAP.find(letter)
- return str(n_row) + t_col
- #Подготовка описаний
- def prepareDesc(dsc):
- #жкранируем кавычки
- return dsc.replace('"','\\"')
- #печать комнаты в Tads-файл уровня
- def print_room(coord,lit_name,lit_desc,cell_type,g_type,startZond,startKit,startVint,startSonya):
- with open('level' + str(levelId) + '.t', 'a') as f:
- f.write('room' + coord_to_pos(coord) + 'Level' + str(levelId) + ' :' + cell_type + '\n')
- f.write(' levelId=' + str(levelId) + '\n')
- f.write(' coord=' + "'" + coord.encode('cp1251') + "'\n")
- f.write(' groundType=' + g_type + '\n')
- f.write(' lit_name=' + "'" + lit_name.encode('cp1251') + "'\n")
- f.write(' lit_desc=' + "'" + prepareDesc(lit_desc).encode('cp1251') + "'\n")
- if startZond == True: f.write(' startZond = true\n')
- if startKit == True: f.write(' startKit = true\n')
- if startVint == True: f.write(' startVint = true\n')
- if startSonya == True: f.write(' startSonya = true\n')
- f.write(";\n\n")
- return
- def print_info(caption,brief,final_link,next_lev,code):
- with open('level' + str(levelId) + '.t', 'a') as f:
- f.write('InfoLevel' + str(levelId) + ' : LevelInfo\n')
- f.write(' levelId=' + str(levelId) + '\n')
- f.write(' caption=' + "'" + prepareDesc(caption).encode('cp1251') + "'" + '\n')
- f.write(' task=' + "'" + prepareDesc(brief).encode('cp1251') + "'" + '\n')
- f.write(' finalTextFun=' + final_link + '\n')
- f.write(' nextLevelId=' + next_lev + '\n')
- f.write(' code=' + "'" + code.encode('cp1251') + "'" + '\n')
- f.write(";\n\n")
- return
- def print_object_header(pos,obj_class,obj_name,obj_desc,gender,coord):
- with open('level' + str(levelId) + '.t', 'a') as f:
- f.write(obj_class + str(pos) + 'Level' + str(levelId) + ' : ' + obj_class + ' \n')
- f.write(' levelId=' + str(levelId) + '\n')
- f.write(' coord=' + "'" + coord.encode('cp1251') + "'\n")
- list_desc = obj_name.split(' ')
- for i in range(len(list_desc)):
- if gender[0] == 'M': list_desc[i] += ('/1м').decode('cp1251')
- elif gender[0] == 'F': list_desc[i] += ('/1ж').decode('cp1251')
- else: list_desc[i] += ('/1').decode('cp1251')
- if len(gender) == 2 and gender[1] == 'O': list_desc[i] += ('о').decode('cp1251')
- if i != len(list_desc) - 1: list_desc[i] += ('п').decode('cp1251')
- gendered_desc = ' '.join(list_desc)
- f.write(' desc=' + "'" + gendered_desc.encode('cp1251') + "'\n")
- f.write(' ldesc=' + '"' + prepareDesc(obj_desc).encode('cp1251') + '"\n')
- if (gender[0] == 'M'): f.write(' isHim=true\n')
- elif (gender[0] == 'F'): f.write(' isHer=true\n')
- return
- def print_object_footer():
- with open('level' + str(levelId) + '.t', 'a') as f:
- f.write(";\n\n")
- return
- def print_object_path(coord):
- with open('level' + str(levelId) + '.t', 'a') as f:
- coord_list = coord.split(',')
- new_list = []
- for coord in coord_list:
- new_list.append("'" + coord.upper().replace(' ','').encode('cp1251') + "'")
- final_path = ' '.join(new_list)
- f.write(' path=[' + final_path + ']\n')
- return
- #Гранат Патронов Капканов Аптечек Капсул превращения
- def print_ammo_num(grenades,bullets,kap,apt,trans):
- with open('level' + str(levelId) + '.t', 'a') as f:
- f.write(' grenades=' + str(grenades) + '\n')
- f.write(' bullets=' + str(bullets) + '\n')
- f.write(' capcans=' + str(kap) + '\n')
- f.write(' aids=' + str(apt) + '\n')
- f.write(' capsules=' + str(trans) + '\n')
- return
- def print_transport_hit(isKill):
- if isKill is True:
- with open('level' + str(levelId) + '.t', 'a') as f:
- f.write(' canKill = true\n')
- return
- def print_dialogue(dia_caption,dia_link,dia_text):
- with open('level' + str(levelId) + '.t', 'a') as f:
- f.write('\n//' + dia_caption.encode('cp1251') + '\n')
- f.write(dia_link + ': function' + '\n')
- f.write('{' + '\n')
- list_desc = prepareDesc(dia_text).split('\n')
- for i in range(len(list_desc)):
- f.write('"' + list_desc[i].encode('cp1251') + '\\n";\n')
- f.write('}' + '\n')
- return
- ############################################
- #Обработчики
- #карты пар
- info_pair_map = {}
- def process_info_block(row):
- global info_pair_map
- if len(row) >= 2:
- info_key = get_cell_text(row[0]).lower() #ключи всегда сравниваются без регистра
- info_val = get_cell_text(row[1])
- info_pair_map[info_key] = info_val
- return
- #раскладываем пары по полкам и проверям на наличие всего необходимого
- def finalize_info():
- caption = 'undefined'
- brief = 'undefined'
- final_link = 'nil'
- next_lev = '0'
- code = ''
- for key in info_pair_map:
- if KEY_INFO_CAPTION in key: caption = info_pair_map[key]
- elif KEY_INFO_BREEF in key: brief = info_pair_map[key]
- elif KEY_INFO_FINAL in key: final_link = info_pair_map[key]
- elif KEY_INFO_NEXT in key: next_lev = info_pair_map[key]
- elif KEY_INFO_CODE in key: code = info_pair_map[key]
- next_lev = next_lev.replace('.0','')
- print_info(caption,brief,final_link,next_lev,code)
- return
- #обработка карты
- game_map = {}
- def process_map_block(row):
- global game_map
- global map_row
- global ALPHA_FOR_MAP
- if len(row) > 0:
- map_col = 0
- for cell in row:
- if map_col > 0 and map_row > 0 and get_cell_text(cell) is not None:
- ind = ALPHA_FOR_MAP[map_col] + str(get_cell_int(row[0])) #формируем индекс для ячейки
- print_to_console(ind,False)
- print_to_console(get_cell_text(cell),False)
- game_map[ind] = get_cell_text(cell)
- map_col += 1
- return
- #распечатываем карту
- def finalize_map():
- global game_map
- room_total = 0
- #обрабатываем все ячейки
- for cell in game_map:
- if game_map[cell] is not None:
- str_list = game_map[cell].split('\n')
- #print_to_console(game_map[cell],False)
- if len(str_list) >= 2:
- #отделяем заголовок от лит. описания
- header = str_list[0]
- del str_list[0]
- lit_desc = ' '.join(str_list)
- lit_desc = lit_desc.replace('\n','')
- #разделяем лит. название локации и параметры карты
- header_param = header.split('.')
- lit_header = header_param[0]
- del header_param[0]
- header_param = '.'.join(header_param)
- header_param = header_param.lower()
- #определяем тип земли
- g_type = 'GROUND_TYPE_NORMAL'
- if GROUND_TYPE_ROCK in header_param: g_type = 'GROUND_TYPE_ROCK'
- elif GROUND_TYPE_WATER in header_param: g_type = 'GROUND_TYPE_WATER'
- elif GROUND_TYPE_WALL in header_param: g_type = 'GROUND_TYPE_WALL'
- #определяем тип ячейки
- cell_type = 'Cell'
- if CELL_TYPE_FINAL in header_param: cell_type = 'FinalCell'
- #определяем старт персонажей
- startZond = False
- startKit = False
- startVint = False
- startSonya = False
- if START_TYPE_ZOND in header_param: startZond = True
- if START_TYPE_KIT in header_param: startKit = True
- if START_TYPE_VINT in header_param: startVint = True
- if START_TYPE_SONYA in header_param: startSonya = True
- #печать комнаты
- print_room(cell,lit_header,lit_desc,cell_type,g_type,startZond,startKit,startVint,startSonya)
- room_total += 1
- else:
- print('Error parse header')
- print_to_console(game_map[cell],True)
- print('Created map, rooms: ' + str(room_total))
- return
- #обработка объектов
- def get_tads_class(str):
- CLASS_MAP = {'бык'.decode('cp1251'):'BykMonster',
- 'бочка'.decode('cp1251'):'GasTank',
- 'коробка'.decode('cp1251'):'AmmoBox',
- 'машина'.decode('cp1251'):'Transport',
- 'дом'.decode('cp1251'):'House'}
- if str in CLASS_MAP: return CLASS_MAP[str]
- return None
- def get_tads_gender(str):
- CLASS_MAP = {'муж.'.decode('cp1251'):'M',
- 'жен.'.decode('cp1251'):'F',
- 'ср.'.decode('cp1251'):'C' ,
- 'муж.од.'.decode('cp1251'):'MO',
- 'жен.од.'.decode('cp1251'):'FO',
- 'ср.од.'.decode('cp1251'):'CO' }
- return CLASS_MAP[str]
- globalObjPos = 0
- isUserHeaderRow = True
- def process_objects_block(obj_pos,row):
- global isUserHeaderRow
- #пропускаем первую строку с описанием колонок
- if isUserHeaderRow == True:
- return
- #получаем инфу
- #Класс Имя Род Описание Локация Маршрут (для быков) Гранат Патронов
- #Капканов Аптечек Капсул превращения
- obj_class = get_cell_text(row[0]).lower().replace(' ','')
- curr_class = get_tads_class(obj_class)
- if (curr_class == None): return
- obj_name = get_cell_text(row[1])
- obj_gender = get_cell_text(row[2]).lower().replace(' ','')
- curr_gender = get_tads_gender(obj_gender)
- obj_ldesc = get_cell_text(row[3])
- obj_loc = get_cell_text(row[4])
- print('proc obj class: ' + curr_class)
- #печатаем базу
- print_object_header(obj_pos,curr_class,obj_name,obj_ldesc,curr_gender,obj_loc)
- #печатаем уникальные данные для классов
- if curr_class == 'BykMonster':
- print_to_console(get_cell_text(row[5]),False)
- if get_cell_text(row[5]) is not None: print_object_path(get_cell_text(row[5]))
- elif curr_class == 'AmmoBox':
- grenades = 0
- bullets = 0
- kap = 0
- apt = 0
- trans = 0
- if get_cell_text(row[6]) is not None: grenades = get_cell_int(row[6])
- if get_cell_text(row[7]) is not None: bullets = get_cell_int(row[7])
- if get_cell_text(row[8]) is not None: kap = get_cell_int(row[8])
- if get_cell_text(row[9]) is not None: apt = get_cell_int(row[9])
- if get_cell_text(row[10]) is not None: trans = get_cell_int(row[10])
- print_ammo_num(grenades,bullets,kap,apt,trans)
- elif curr_class == 'Transport':
- isKillTransport = False
- if get_cell_text(row[11]) is not None and get_cell_int(row[11]) > 0: isKillTransport = True
- print_transport_hit(isKillTransport)
- #печатаем окончание класса
- print_object_footer()
- return
- def process_dialogue_block(row):
- global isUserHeaderRow
- print('proc dia...')
- #пропускаем первую строку с описанием колонок
- if isUserHeaderRow == True:
- return
- #получаем инфу
- #Название Ссылка Текст
- dia_caption = get_cell_text(row[0])
- dia_link = get_cell_text(row[1]).lower().replace(' ','')
- dia_text = get_cell_text(row[2])
- #печатаем диалог
- print_dialogue(dia_caption,dia_link,dia_text)
- return
- ############################################
- #загружаем книгу
- wb = openpyxl.load_workbook('kombi2map.xlsx')
- #распечатываем все листки
- print('Total sheets:')
- print(wb.get_sheet_names())
- ts = time.time()
- time_st = datetime.datetime.fromtimestamp(ts).strftime('%d.%m.%Y %H:%M:%S')
- #для каждого листка
- for ws in wb.worksheets:
- state = INIT_BLOCK
- #код уровня
- levelId = get_cell_int(ws['A1'])
- print('Process level ' + str(levelId) + '...')
- #очищаем карту
- open('level' + str(levelId) + '.t', 'w')
- with open('level' + str(levelId) + '.t', 'a') as f:
- f.write('//GENERATED: ' + time_st + '\n\n')
- game_map = {}
- map_row = 0
- for row in ws.iter_rows():
- if len(row) > 0:
- try:
- block_cell = row[0]
- block_text = get_cell_text(block_cell).lower()
- #проверяем состояние, в котором идёт обработка
- if state == BLOCK_WAIT:
- if BLOCK_INFO in block_text:
- print('Start info')
- state = BLOCK_INFO
- elif BLOCK_MAP in block_text:
- print('Start map')
- state = BLOCK_MAP
- elif BLOCK_OBJ in block_text:
- print('Start obj')
- isUserHeaderRow = True
- globalObjPos = 1
- state = BLOCK_OBJ
- elif DIALOGUE_EVENT in block_text:
- print('Start dialogue')
- isUserHeaderRow = True
- state = DIALOGUE_EVENT
- elif state == BLOCK_INFO:
- if BLOCK_END in block_text:
- finalize_info()
- print('End info')
- state = BLOCK_WAIT
- else:
- process_info_block(row)
- elif state == BLOCK_MAP:
- if BLOCK_END in block_text:
- finalize_map()
- state = BLOCK_WAIT
- else:
- process_map_block(row)
- map_row+=1
- elif state == BLOCK_OBJ:
- if BLOCK_END in block_text:
- print('End obj')
- state = BLOCK_WAIT
- else:
- process_objects_block(globalObjPos,row)
- isUserHeaderRow = False
- globalObjPos+=1
- elif state == DIALOGUE_EVENT:
- if BLOCK_END in block_text:
- print('End dialogue')
- state = BLOCK_WAIT
- else:
- process_dialogue_block(row)
- isUserHeaderRow = False
- except AttributeError:
- continue
- #break #DEBUG
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement