# Script for the Unforgettable Banquet of Lursendis item.
# Idea courtesy Yann Chachkoff.
#
# Copyright 2007 Nicolas Weeger
# Released as GPL
#
# This script will teleport the player to a food-filled map. It only works
# once a (ingame) day.
# Applying the tome while in the map will teleport the player back to his starting place.
# Book can only be applied when in player's inventory, so player can get back to the world.
#
# Map is generated by the script itself, and given a unique name to avoid collision.
#
# Player is replaced with a statue so the spot stays free during his trip.
# To avoid colliding with an existing map, created map will have a unique map.
# Everything in the map is randomly chosen.

import Crossfire
import random
import os.path

# map sizes
size_x = 15
size_y = 15

# what foods to put in the map
foods = [ 'fishfood', 'food', 'bag_popcorn', 'apple', 'cheeseburger', 'loaf', 'tomato', 'waybread', 'roast_bird', 'orange', 'leg_mutton' ]
# what floors can be used
floors = [ 'woodfloor', 'flagstone', 'dirtfloor' ]
# what walls can be used - only put the base name
walls = [ 'flagstone', 'dwall', 'timberwall', 'stwall' ]

# what to replace the player with. Should block all movement
replace_with = [ 'd_statue', 'statue', 'statue2' ]

def get_one(what):
	'''Return a random choice in what, which should be an array.'''
	return what[ random.randint( 1, len(what) ) - 1 ]

def return_to_bed():
	'''Teleport player back to bed of reality. Only in emergency.'''
	flags = 0
	if (act.BedMap.find(Crossfire.PlayerDirectory()) != -1):
		# Unique map
		flags = 2
	dest = Crossfire.ReadyMap(act.BedMap, flags)
	if (dest == None):
		# Ok, this is real bad. Let player handle the situation - worse case, call to DMs or WoR manually.
		act.Message('The %s whines really loudly.'%l.Name)
		return

	act.Teleport(dest, act.BedX, act.BedY)

def do_back():
	'''Teleport the player back to his starting point.'''
	x = l.ReadKey('banquet_x')
	y = l.ReadKey('banquet_y')
	mn = l.ReadKey('banquet_map')
	rw = l.ReadKey('banquet_rw')

	l.WriteKey('banquet_x', '', 0)
	l.WriteKey('banquet_y', '', 0)
	l.WriteKey('banquet_map', '', 0)
	l.WriteKey('banquet_rw', '', 0)

	if x == '' or y == '' or mn == '':
		# Logic error, but can't be helped - teleport player back to his bed of reality
		act.Message('You feel a distorsion of reality!')
		return_to_bed()
		return

	# find and remove statue in the map
	dest = Crossfire.ReadyMap(mn)
	if (dest == None):
		# Random map, probably? Let the player teleport back him/herself.
		act.Message('The %s whines something. You barely understand it can\'t take you back to your starting point.'%l.Name)
		return_to_bed()
		return

	# Remove statue - let's assume it's found, or was removed due to map reset.
	st = dest.ObjectAt(int(x), int(y))
	while st != None:
		if (st.ArchName != rw):
			st = st.Above
			continue;
		st.Remove()
		break;

	act.Message('You feel a powerful force engulf you.')
	act.Teleport(dest, int(x), int(y))

def do_banquet():
	'''Teleports the player to the banquet map, if not used since one day. '''

	now = str(Crossfire.GetTime()[0]) + '-' + str(Crossfire.GetTime()[1]) + '-' + str(Crossfire.GetTime()[2])

	l = Crossfire.WhoAmI()
	act = Crossfire.WhoIsActivator()

	last = l.ReadKey('banquet_last')


	if (last == now):
		act.Message('You read the %s but nothing happens.'%l.Name)
		return;

	l.WriteKey('banquet_last', now, 1)

	# map generation
	m = Crossfire.CreateMap(size_x, size_y)
	m.Path = os.path.join(Crossfire.ScriptName(), Crossfire.WhoIsActivator().Name)
	floor = get_one(floors)

	# First, let's put the floors
	for x in range(size_x):
		for y in range(size_y):
			fl = Crossfire.CreateObjectByName(floor)
			fl.Teleport(m, x, y)

	# Put walls.
	wall = get_one(walls)
	# top left
	m.CreateObject(wall + '_2_2_2', 0, 0)
	# top right
	m.CreateObject(wall + '_2_2_3', size_x - 1, 0)
	# bottom left
	m.CreateObject(wall + '_2_2_1', 0, size_y - 1)
	# bottom right
	m.CreateObject(wall + '_2_2_4', size_x - 1, size_y - 1)
	# top and bottom parts
	for x in range(size_x - 2):
		m.CreateObject(wall + '_2_1_2', x + 1, 0)
		m.CreateObject(wall + '_2_1_2', x + 1, size_y - 1)
	# left and right parts
	for y in range(size_y - 2):
		m.CreateObject(wall + '_2_1_1', 0, y + 1)
		m.CreateObject(wall + '_2_1_1', size_x - 1, y + 1)

	# Food itself
	for x in range(size_x-2):
		for y in range(size_y-2):
			m.CreateObject(get_one(foods), x + 1, y + 1).GodGiven = 1

	# Store player's current location
	x = act.X
	y = act.Y
	im = act.Map
	rw = get_one(replace_with)

	l.WriteKey('banquet_x', str(x), 1)
	l.WriteKey('banquet_y', str(y), 1)
	l.WriteKey('banquet_map', im.Path, 1)
	l.WriteKey('banquet_rw', rw, 1)

	# Teleport
	act.Message('You feel grabbed by some powerful force.')
	act.Teleport(m, int(( size_x - 1 ) / 2), int((size_y - 1) / 2))

	# Keep free spot by putting a statue
	statue = im.CreateObject(rw, x, y)
	statue.Name = '%s\'s statue'%act.Name
	statue.Message = 'Gone eating.'

l = Crossfire.WhoAmI()
act = Crossfire.WhoIsActivator()

if l.Env != act:
	act.Message('You try to open the %s, but it seems to flee from you.'%l.Name)
elif (act.Map.Path.find(Crossfire.ScriptName()) != -1):
	do_back()
else:
	do_banquet()

Crossfire.SetReturnValue(1)
