/[enigma]/enigma/data/levels/ralf_sokoban.lua
ViewVC logotype

Diff of /enigma/data/levels/ralf_sokoban.lua

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.9 by reallysoft, Sun Apr 20 19:47:56 2003 UTC revision 1.10 by reallysoft, Tue Apr 29 20:20:17 2003 UTC
# Line 45  oxyd_flavors = { "a", "b", "c", "d" } Line 45  oxyd_flavors = { "a", "b", "c", "d" }
45    
46  shogunLaser = 0 -- if set to 1 then lasers are used to activate oxyds (this only works with shogun stones)  shogunLaser = 0 -- if set to 1 then lasers are used to activate oxyds (this only works with shogun stones)
47    
48  -- global variables  -- Symmetry information:
49    xsymm = 0
50    ysymm = 0
51    psymm = 0
52    
53  triggers = 0  triggers = 0
54  doors = 0  doors = 0
55  lasers = 0  lasers = 0
56    
57  space_count = 0 -- count occurances of space (outside level)  space_count = 0 -- count occurances of space (outside level)
58    
59  triggerstate = "" -- current state of the triggers  triggerstate = "" -- current state of the triggers
# Line 88  function init_shuffle() Line 93  function init_shuffle()
93        shuffle[count] = set[sel]        shuffle[count] = set[sel]
94        set[sel] = set[left]        set[sel] = set[left]
95        left = left-1        left = left-1
96        debug("shuffle["..count.."]="..shuffle[count])  --      debug("shuffle["..count.."]="..shuffle[count])
97     end     end
98    
99     local settrig = {}     local settrig = {}
# Line 100  function init_shuffle() Line 105  function init_shuffle()
105        shuffletrig[count] = settrig[sel]        shuffletrig[count] = settrig[sel]
106        settrig[sel] = settrig[left]        settrig[sel] = settrig[left]
107        left = left-1        left = left-1
108        debug("shuffletrig["..count.."]="..shuffletrig[count])  --      debug("shuffletrig["..count.."]="..shuffletrig[count])
109     end     end
110  end  end
111    
# Line 317  function is_in_restricted_area(p) Line 322  function is_in_restricted_area(p)
322     return 2 -- unknown     return 2 -- unknown
323  end  end
324    
325    --function symmetric_position(x,y,w,h)
326    --   if (xsymm==1) then return w-(x-xlo)+xlo,y end
327    --   if (ysymm==1) then return x,h-(y-ylo)+ylo end
328    --   if (psymm==1) then return h-(y-ylo)+xlo,x-xlo+ylo end
329    --   return x,y
330    --end
331    
332    function symmetric_position(x,y,w,h)
333       if (xsymm==1) then return w-x+1,y end
334       if (ysymm==1) then return x,h-y+1 end
335       if (psymm==1) then return h-y+1,x end
336       return x,y
337    end
338    
339    removed_indices={}
340    removed = 0
341    
342    function rs_remove_oxyd(p,w,h)
343       removed_indices={}
344       removed = 0
345    --   debug("rs_remove_oxyd("..p..","..w..","..h..")")
346       local x1,y1 = position[p][1],position[p][2]
347       if (xsymm+ysymm+psymm) then
348          local symmcount = 1
349          if (psymm==1) then symmcount=3 end
350          for c=1,symmcount do
351             local x2,y2 = symmetric_position(x1,y1,w,h)
352    --         debug("symmetric_position = "..x2.."/"..y2);
353             for q=1,positions do
354                --         debug("qpos="..position[q][1].."/"..position[q][2]);
355                if ((q~=p) and (x2==position[q][1]) and (y2==position[q][2])) then
356    --               debug("opposite symmetric position: "..position[q][1].."/"..position[q][2].." num="..q);
357                   tremove(position,q)
358                   removed = removed+1
359                   removed_indices[removed] = q
360                   positions = positions-1
361                   if (q<p) then p = p-1 end
362                   break
363                end
364             end
365             x1,y1 = x2,y2
366          end
367       end
368    
369    --   debug("position: "..position[p][1].."/"..position[p][2].." num="..p);
370       tremove(position,p)
371       removed = removed+1
372       removed_indices[removed] = p
373       positions = positions-1
374    end
375    
376  maxoxyds = 999  maxoxyds = 999
377    
378  function install_oxyds(w,h) -- uses Nat's method (see nat7.lua)  function install_oxyds(w,h) -- uses Nat's method (see nat7.lua)
# Line 338  function install_oxyds(w,h) -- uses Nat' Line 394  function install_oxyds(w,h) -- uses Nat'
394                    else                    else
395                       -- positions with more than 1 adjacent space should never be used as doors                       -- positions with more than 1 adjacent space should never be used as doors
396                       -- (because you may escape there)                       -- (because you may escape there)
397                       spacehere = -1                       if (shogunLaser==0) then
398                            spacehere = -1
399                         else -- does not matter in shogunLaser-mode
400                            -- ensure symmetry
401                            if (xsymm==1 and (x==(w-x+1))) then
402                               spacehere = n -- use oxyd in y direction
403                            end
404                         end
405                    end                    end
406                 end                 end
407    
# Line 353  function install_oxyds(w,h) -- uses Nat' Line 416  function install_oxyds(w,h) -- uses Nat'
416                 end                 end
417              end              end
418    
419              if ((reachable>0) and (spacehere>0)) then              if (((reachable>0) or (shogunLaser==1)) and (spacehere>0)) then
420                 local t = "v";  --               local t = "v";
421                 if (spacehere >= 3) then t="h" end  --               if (spacehere >= 3) then t="h" end
   
                local rx,ry = xlo+x-1,ylo+y-1  
   
422                 positions = positions+1                 positions = positions+1
423                 position[positions] = {rx,ry,rx+xoff[spacehere], ry+yoff[spacehere]}                 position[positions] = {x,y,x+xoff[spacehere], y+yoff[spacehere]}
424              end              end
425           end           end
426        end        end
# Line 397  function install_oxyds(w,h) -- uses Nat' Line 457  function install_oxyds(w,h) -- uses Nat'
457                 end                 end
458              end              end
459              if ((oneighbours>=delif) or (dneighbours>=delif)) then              if ((oneighbours>=delif) or (dneighbours>=delif)) then
460                 tremove(position,p)                 rs_remove_oxyd(p,w,h)
                positions = positions-1  
461                 deleted = 1                 deleted = 1
462                 break                 break
463              end              end
# Line 407  function install_oxyds(w,h) -- uses Nat' Line 466  function install_oxyds(w,h) -- uses Nat'
466     end     end
467    
468     -- delete superfluous oxyds     -- delete superfluous oxyds
469     while ((positions>triggers) or (positions>maxoxyds) or (mod(positions,2)==1)) do     local want_remove = 0
470        tremove(position,random(1,positions));  
471        positions = positions - 1     if (maxoxyds>triggers) then maxoxyds = triggers end
472    
473       if (positions>maxoxyds) then
474          want_remove = positions-maxoxyds
475          debug("maxoxyds="..maxoxyds.." want_remove="..want_remove);
476       end
477    
478       if (mod(positions-want_remove,2)==1) then want_remove = want_remove-1 end
479    
480       debug("positions="..positions.." want_remove="..want_remove);
481    
482       if ((psymm+xsymm+ysymm)>0) then
483          local isSymmetric = {}
484          local sym_count = 0
485          local sym_count_single = 0
486          local per_remove = 0
487    
488          for p=1,positions do isSymmetric[p] = 0 end
489          if (psymm==1) then -- central symmetry
490             per_remove=4
491             for p=1,positions do
492                if (isSymmetric[p]==0) then
493                   local x1,y1 = position[p][1],position[p][2]
494                   local allFound = 1
495                   local index={}
496                   for r=1,3 do
497                      local x2,y2 = symmetric_position(x1,y1,w,h)
498                      local found = 0
499                      for q=1,positions do
500                         if (p~=q and position[q][1]==x2 and position[q][2]==y2) then
501                            local inUse=0
502                            for r2=1,r-1 do
503                               if (index[r2]==q) then inUse=1 break end
504                            end
505                            if (inUse==0) then
506                               found=1
507                               index[r]=q
508                               break
509                            end
510                         end
511                      end
512                      if (found==0) then allFound = 0 break end
513                      x1,y1 = x2,y2
514                   end
515                   if (allFound==1) then
516                      isSymmetric[p]=1
517                      for r=1,3 do isSymmetric[index[r]]=1 end
518                      sym_count = sym_count+4
519                      local array=""
520                      for p=1,positions do array=array..isSymmetric[p] end
521                      debug("isSymmetric="..array);
522                   end
523                end
524             end
525          else
526             per_remove=2
527             for p=1,positions do
528                if (isSymmetric[p]==0) then
529                   local x1,y1 = position[p][1],position[p][2]
530                   local x2,y2 = symmetric_position(x1,y1,w,h)
531    
532                   if (x1==x2 and y1==y2) then
533                      isSymmetric[p] = 2
534                      sym_count_single = sym_count_single+1
535                   else
536                      for q=1,positions do
537                         if (p~=q and position[q][1]==x2 and position[q][2]==y2) then
538                            isSymmetric[p] = 1
539                            isSymmetric[q] = 1
540                            sym_count = sym_count+2
541                            break
542                         end
543                      end
544                   end
545                end
546             end
547          end
548    
549          local assym_count = positions-(sym_count+sym_count_single)
550    
551          debug("positions="..positions.." sym_count="..sym_count.." sym_count_single="..sym_count_single.." assym_count="..assym_count);
552    
553          -- first remove assymetric positions
554          if (assym_count>0 and want_remove>0) then
555             for p=positions,1,-1 do
556                if (isSymmetric[p]==0) then
557                   tremove(position,p);
558                   tremove(isSymmetric,p);
559                   want_remove = want_remove-1
560                   positions = positions-1
561                   assym_count = assym_count-1
562    
563                   if (want_remove==0) then break end
564                end
565             end
566          end
567    
568          -- then remove some symmetric positions
569          while (want_remove>=per_remove) do
570             if (sym_count<per_remove) then error("internal counter error") end
571             local todel = 0
572             for p=1,positions do -- try randomly
573                local q = random(1,positions)
574                if (isSymmetric[q]==1) then todel = q break end
575             end
576             if (todel==0) then -- if failed try by sequence
577                for p=1,positions do
578                   if (isSymmetric[p]==1) then todel=p break end
579                end
580             end
581             if (todel>0) then -- correct isSymmetric
582                rs_remove_oxyd(todel,w,h)
583                if (removed ~= per_remove) then error("internal error: removed ~= per_remove") end
584                sym_count=sym_count-per_remove
585                want_remove = want_remove-per_remove
586                for r=1,removed do
587                   tremove(isSymmetric,removed_indices[r]);
588                end
589             end
590          end
591    
592          -- now remove single symmetric positions
593          while (want_remove>0 and sym_count_single>0) do
594             for p=positions,1,-1 do
595                if (isSymmetric[p]==2) then
596                   tremove(position,p);
597                   tremove(isSymmetric,p);
598                   want_remove = want_remove-1
599                   positions = positions-1
600                   sym_count_single = sym_count_single-1
601    
602                   if (want_remove==0) then break end
603                end
604             end
605          end
606     end     end
607    
608       -- remove random stones for assymetric levels (or if symmetric remove failed)
609    
610       while (want_remove>0) do
611          local p = random(1,positions)
612          tremove(position,p);
613          want_remove = want_remove-1
614          positions=positions-1
615       end
616    
617       if (mod(positions,2)==1) then -- final check for even oxyd count
618          tremove(position,random(1,positions))
619          positions = positions-1
620       end
621    
622       -- end of oxyd removal
623    
624       debug("left oxyds: "..positions);
625    
626     if (positions == 0) then     if (positions == 0) then
627        error("No oxyds.")        error("No oxyds.")
628     end     end
629    
630     if (maxoxyds>positions) then  --   if (maxoxyds>positions) then
631        maxoxyds = positions  --      maxoxyds = positions
632    --   end
633    
634       -- transform to "real" coordinates
635       for p=1,positions do
636          position[p][1] = position[p][1]+xlo-1
637          position[p][2] = position[p][2]+ylo-1
638          position[p][3] = position[p][3]+xlo-1
639          position[p][4] = position[p][4]+ylo-1
640     end     end
641    
642     -- now really set oxyds     -- now really set oxyds
# Line 467  function correct_locked_door_position() Line 686  function correct_locked_door_position()
686  end  end
687    
688  function correct_multi_trigger_doors()  function correct_multi_trigger_doors()
689     if (doors == triggers) then return 1 end -- 1 triggers <-> 1 door => no problem     if (doors == triggers) then return 1 end -- each trigger has exactly one door => no problem
690    
691     local multiTriggeredDoors = triggers-doors     local multiTriggeredDoors = triggers-doors
692     if (multiTriggeredDoors > doors) then multiTriggeredDoors = doors end     if (multiTriggeredDoors > doors) then multiTriggeredDoors = doors end
# Line 492  function correct_door_positions() Line 711  function correct_door_positions()
711     return ok     return ok
712  end  end
713    
714    function choose_symmetry()
715       if (xsymm==1 and ysymm==1) then ysymm=0 end -- prefer x-symmetry
716    
717       while ((xsymm+ysymm+psymm) > 1) do
718          local r = random(1,3)
719          if (r==1) then xsymm = 0
720          elseif (r==2) then ysymm = 0
721          else psymm = 0
722          end
723       end
724    
725       debug("----------------------------------------");
726       if (xsymm==1) then debug("Symmetry: X") end
727       if (ysymm==1) then debug("Symmetry: Y") end
728       if (psymm==1) then debug("Symmetry: central") end
729    end
730    
731  function play_sokoban(level,num)  function play_sokoban(level,num)
732     local w,h = get_map_size(level)     local w,h = get_map_size(level)
733     local tries = 80     local tries = 80
734     local ok = 0     local ok = 0
735    
736       randomseed(enigma.GetTicks())
737       choose_symmetry()
738    
739     while ((tries > 0) and (maxoxyds > 0) and (ok == 0)) do     while ((tries > 0) and (maxoxyds > 0) and (ok == 0)) do
740        init(num-1)        init(num-1)
741        randomseed(enigma.GetTicks())        randomseed(enigma.GetTicks())
# Line 526  function play_sokoban(level,num) Line 765  function play_sokoban(level,num)
765        install_oxyds(w,h)        install_oxyds(w,h)
766        init_shuffle() -- mix trigger-door associations        init_shuffle() -- mix trigger-door associations
767        ok = correct_door_positions()        ok = correct_door_positions()
768        if (ok == 0) then debug("re-initializing.."); end  --      ok = 1
769        tries = tries - 1        if (ok == 0) then
770        if (maxoxyds > 2) then           debug("---------------------------------------- re-initializing..");
          maxoxyds = maxoxyds - 1  
771        end        end
772          tries = tries - 1
773    --      if (maxoxyds > 2) then
774    --         maxoxyds = maxoxyds - 1
775    --      end
776     end     end
777    
778     if (ok==0) then     if (ok==0) then
779        error("Sorry - couldn't correct door positions. Avoiding deadlock (try again)");  --      error("Sorry - couldn't correct door positions. Avoiding deadlock (try again)");
780     end     end
781    
782     triggerstate = strrep("0",triggers)     triggerstate = strrep("0",triggers)

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.10

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26